Skip to content

Commit b0af84e

Browse files
author
Pooya Parsa
committedNov 16, 2017
feat(workbox): rewrite with better template support
1 parent 3c7aa7d commit b0af84e

File tree

3 files changed

+116
-30
lines changed

3 files changed

+116
-30
lines changed
 

Diff for: ‎packages/workbox/index.js

+103-30
Original file line numberDiff line numberDiff line change
@@ -1,76 +1,149 @@
11
const path = require('path')
22
const swBuild = require('workbox-build')
3+
const { readFileSync, writeFileSync } = require('fs')
4+
const hashSum = require('hash-sum')
5+
const debug = require('debug')('nuxt:pwa:workbox')
36

47
const fixUrl = url => url.replace(/\/\//g, '/').replace(':/', '://')
58
const isUrl = url => url.indexOf('http') === 0 || url.indexOf('//') === 0
69

7-
module.exports = function nuxtWorkbox (options) {
10+
// =============================================
11+
// workboxModule
12+
// =============================================
13+
14+
module.exports = function nuxtWorkbox (moduleOptions) {
15+
const options = Object.assign({}, moduleOptions, this.options.workbox)
16+
const ctx = { options }
17+
818
if (this.options.dev) {
919
return
1020
}
1121

12-
// routerBase and publicPath
22+
this.nuxt.plugin('build', builder => {
23+
debug('Adding workbox')
24+
getRouterBase.call(this, ctx)
25+
workboxInject.call(this, ctx)
26+
emitAssets.call(this, ctx)
27+
addTemplates.call(this, ctx)
28+
})
29+
}
30+
31+
// =============================================
32+
// getRouterBase
33+
// =============================================
34+
35+
function getRouterBase (ctx) {
1336
const routerBase = this.options.router.base
1437
let publicPath = fixUrl(`${routerBase}/${this.options.build.publicPath}`)
1538
if (isUrl(this.options.build.publicPath)) { // CDN
1639
publicPath = this.options.build.publicPath
1740
if (publicPath.indexOf('//') === 0) {
18-
publicPath = '/' + publicPath // escape fixUrl
41+
publicPath = '/' + publicPath // Escape fixUrl
1942
}
2043
}
2144

22-
const swFileName = 'sw.js'
45+
ctx.routerBase = routerBase
46+
ctx.publicPath = publicPath
47+
}
48+
49+
// =============================================
50+
// addTemplates
51+
// =============================================
52+
53+
function addTemplates (ctx) {
54+
// Add sw.template.js
55+
this.addTemplate({
56+
src: path.resolve(__dirname, 'templates/sw.template.js'),
57+
fileName: 'sw.template.js',
58+
options: {
59+
importPath: ctx.wbDst,
60+
wb: ctx.workboxOptions
61+
}
62+
})
63+
64+
// Add sw.plugin.js
65+
const swURL = `${ctx.routerBase}/${ctx.options.swURL || 'sw.js'}`
66+
this.addPlugin({
67+
src: path.resolve(__dirname, 'templates/sw.plugin.js'),
68+
ssr: false,
69+
fileName: 'sw.plugin.js',
70+
options: {
71+
swURL: fixUrl(swURL),
72+
swScope: fixUrl(`${ctx.routerBase}/`)
73+
}
74+
})
75+
}
2376

24-
// Use swBuild to generate sw file
25-
// We set dest to static dir that is served as / to allow global sw scope
77+
// =============================================
78+
// emitAssets
79+
// =============================================
80+
81+
function emitAssets (ctx) {
82+
const assets = []
83+
const emitAsset = (path, name, ext = 'js') => {
84+
const source = readFileSync(path)
85+
const hash = hashSum(source)
86+
const dst = `${name}.${hash}.${ext}`
87+
assets.push({source, dst})
88+
return dst
89+
}
90+
91+
// Write assets after build
92+
this.nuxt.plugin('build', builder => {
93+
builder.plugin('built', () => {
94+
assets.forEach(({source, dst}) => {
95+
writeFileSync(path.resolve(this.options.buildDir, 'dist', dst), source, 'utf-8')
96+
})
97+
})
98+
})
99+
100+
// workbox.js
101+
let wbPath = require.resolve('workbox-sw')
102+
if (ctx.options.dev) {
103+
wbPath = wbPath.replace(/prod/g, 'dev')
104+
}
105+
ctx.wbDst = fixUrl(ctx.publicPath + '/' + emitAsset(wbPath, 'workbox' + (ctx.options.dev ? '.dev' : '')))
106+
}
107+
108+
// =============================================
109+
// workboxInject
110+
// =============================================
111+
112+
function workboxInject (ctx) {
26113
// https://workboxjs.org/reference-docs/latest/module-workbox-build.html#.generateSW
27-
const workboxOptions = Object.assign({
28-
swDest: path.resolve(this.options.srcDir, 'static', swFileName),
114+
ctx.workboxOptions = Object.assign({
115+
swSrc: path.resolve(this.options.buildDir, 'sw.template.js'),
116+
swDest: path.resolve(this.options.srcDir, 'static', 'sw.js'),
29117
directoryIndex: '/',
30118
cacheId: process.env.npm_package_name + '_' + process.env.npm_package_version,
31119
clientsClaim: true,
32120
globPatterns: ['**/*.{js,css}'],
33121
globDirectory: path.resolve(this.options.buildDir, 'dist'),
34122
modifyUrlPrefix: {
35-
'': fixUrl(publicPath)
123+
'': fixUrl(ctx.publicPath)
36124
},
37125
runtimeCaching: [
38126
// Cache routes if offline
39127
{
40-
urlPattern: fixUrl(routerBase + '/**'),
128+
urlPattern: fixUrl(ctx.routerBase + '/**'),
41129
handler: 'networkFirst'
42130
},
43131
// Cache other _nuxt resources runtime
44132
// They are hashed by webpack so are safe to loaded by cacheFirst handler
45133
{
46-
urlPattern: fixUrl(publicPath + '/**'),
134+
urlPattern: fixUrl(ctx.publicPath + '/**'),
47135
handler: 'cacheFirst'
48136
}
49137
]
50-
}, options)
138+
}, ctx.options)
51139

52-
// Use nuxt plugins to prevent race conditions with webpack plugin
53-
// (https://github.com/nuxt-community/modules/issues/110)
54140
this.nuxt.plugin('build', builder => {
55141
builder.plugin('built', () => {
56-
if (workboxOptions.swSrc) {
57-
return swBuild.injectManifest(workboxOptions)
58-
} else {
59-
return swBuild.generateSW(workboxOptions)
60-
}
142+
const opts = Object.assign({}, ctx.workboxOptions)
143+
delete opts.runtimeCaching
144+
return swBuild.injectManifest(opts)
61145
})
62146
})
63-
64-
// Register runtime plugin
65-
const swURL = `${routerBase}/${options.swURL || swFileName}`
66-
this.addPlugin({
67-
src: path.resolve(__dirname, 'plugin.js'),
68-
ssr: false,
69-
options: {
70-
swURL: fixUrl(swURL),
71-
swScope: fixUrl(`${routerBase}/`)
72-
}
73-
})
74147
}
75148

76149
module.exports.meta = require('./package.json')
File renamed without changes.

Diff for: ‎packages/workbox/templates/sw.template.js

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
importScripts('<%= options.importPath %>')
2+
3+
const workboxSW = new self.WorkboxSW({
4+
cacheId: '<%= options.wb.cacheId %>',
5+
clientsClaim: <%= options.wb.clientsClaim %>,
6+
directoryIndex: '<%= options.wb.directoryIndex %>'
7+
})
8+
9+
workboxSW.precache([])
10+
11+
<% options.wb.runtimeCaching.forEach(r => { %>
12+
workboxSW.router.registerRoute('<%= r.urlPattern %>', workboxSW.strategies.<%= r.handler %>({}), 'GET')
13+
<% }) %>

0 commit comments

Comments
 (0)