From db4c23babe01f1257e0c0b9adbcaa9871f564d4a Mon Sep 17 00:00:00 2001 From: aweikalee Date: Sun, 18 Nov 2018 16:58:07 +0800 Subject: [PATCH 1/2] manifest.json will be generated by cli-plugin-pwa --- packages/@vue/cli-plugin-pwa/README.md | 15 ++++++- .../generator/template/public/manifest.json | 20 --------- .../@vue/cli-plugin-pwa/lib/HtmlPwaPlugin.js | 45 ++++++++++++++++++- 3 files changed, 58 insertions(+), 22 deletions(-) delete mode 100644 packages/@vue/cli-plugin-pwa/generator/template/public/manifest.json diff --git a/packages/@vue/cli-plugin-pwa/README.md b/packages/@vue/cli-plugin-pwa/README.md index 8a65cfba79..af28355c43 100644 --- a/packages/@vue/cli-plugin-pwa/README.md +++ b/packages/@vue/cli-plugin-pwa/README.md @@ -54,7 +54,7 @@ file, or the `"vue"` field in `package.json`. - Default: `'default'` - **pwa.assetsVersion** - + - Default: `''` This option is used if you need to add a version to your icons and manifest, against browser’s cache. This will append `?v=` to the URLs of the icons and manifest. @@ -65,6 +65,19 @@ file, or the `"vue"` field in `package.json`. The path of app’s manifest. +- **pwa.manifestOptions** + + - Default: `{}` + + The object will be used to generate the `manifest.json` + + If the following attributes are not defined in the object, the options of `pwa` or default options will be used instead. + - name: `pwa.name` + - short_name: `pwa.name` + - start_url: `'.'` + - display: `'standalone'` + - theme_color: `pwa.themeColor` + - **pwa.iconPaths** - Defaults: diff --git a/packages/@vue/cli-plugin-pwa/generator/template/public/manifest.json b/packages/@vue/cli-plugin-pwa/generator/template/public/manifest.json deleted file mode 100644 index e1f44608f9..0000000000 --- a/packages/@vue/cli-plugin-pwa/generator/template/public/manifest.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "name": "<%- rootOptions.projectName %>", - "short_name": "<%- rootOptions.projectName %>", - "icons": [ - { - "src": "./img/icons/android-chrome-192x192.png", - "sizes": "192x192", - "type": "image/png" - }, - { - "src": "./img/icons/android-chrome-512x512.png", - "sizes": "512x512", - "type": "image/png" - } - ], - "start_url": "./index.html", - "display": "standalone", - "background_color": "#000000", - "theme_color": "#4DBA87" -} diff --git a/packages/@vue/cli-plugin-pwa/lib/HtmlPwaPlugin.js b/packages/@vue/cli-plugin-pwa/lib/HtmlPwaPlugin.js index b5f060054d..68aa476c78 100644 --- a/packages/@vue/cli-plugin-pwa/lib/HtmlPwaPlugin.js +++ b/packages/@vue/cli-plugin-pwa/lib/HtmlPwaPlugin.js @@ -7,7 +7,26 @@ const defaults = { appleMobileWebAppCapable: 'no', appleMobileWebAppStatusBarStyle: 'default', assetsVersion: '', - manifestPath: 'manifest.json' + manifestPath: 'manifest.json', + manifestOptions: {} +} + +const defaultManifest = { + icons: [ + { + "src": "./img/icons/android-chrome-192x192.png", + "sizes": "192x192", + "type": "image/png" + }, + { + "src": "./img/icons/android-chrome-512x512.png", + "sizes": "512x512", + "type": "image/png" + } + ], + start_url: '.', + display: 'standalone', + background_color: "#000000" } const defaultIconPaths = { @@ -109,6 +128,30 @@ module.exports = class HtmlPwaPlugin { cb(null, data) }) + + + }) + + compiler.hooks.emit.tapAsync(ID, (data, cb) => { + const { + name, + themeColor, + manifestPath, + manifestOptions + } = this.options + const publicOptions = { + name, + short_name: name, + theme_color: themeColor + } + const outputManifest = JSON.stringify( + Object.assign(publicOptions, defaultManifest, manifestOptions) + ) + data.assets[manifestPath] = { + source: () => outputManifest, + size: () => outputManifest.length + } + cb(null, data) }) } } From 79ac0dc35ac3f6d68fab4cd272774b2a965913ab Mon Sep 17 00:00:00 2001 From: aweikalee Date: Tue, 26 Mar 2019 15:46:34 +0800 Subject: [PATCH 2/2] feat: generate manifest.json. merge old manifest.json, and throw warn. --- packages/@vue/cli-plugin-pwa/README.md | 18 +++++++++- .../__tests__/pwaPlugin.spec.js | 22 ++++++++++++ packages/@vue/cli-plugin-pwa/index.js | 4 ++- .../@vue/cli-plugin-pwa/lib/HtmlPwaPlugin.js | 36 +++++++++++++++++-- 4 files changed, 76 insertions(+), 4 deletions(-) diff --git a/packages/@vue/cli-plugin-pwa/README.md b/packages/@vue/cli-plugin-pwa/README.md index af28355c43..a1cdb7b768 100644 --- a/packages/@vue/cli-plugin-pwa/README.md +++ b/packages/@vue/cli-plugin-pwa/README.md @@ -74,8 +74,24 @@ file, or the `"vue"` field in `package.json`. If the following attributes are not defined in the object, the options of `pwa` or default options will be used instead. - name: `pwa.name` - short_name: `pwa.name` - - start_url: `'.'` + - icons: + ```js + [ + { + src: './img/icons/android-chrome-192x192.png', + sizes: '192x192', + type: 'image/png' + }, + { + src: './img/icons/android-chrome-512x512.png', + sizes: '512x512', + type: 'image/png' + } + ] + ``` + - start_url: `'./index.html'` - display: `'standalone'` + - background_color: `'#000000'` - theme_color: `pwa.themeColor` - **pwa.iconPaths** diff --git a/packages/@vue/cli-plugin-pwa/__tests__/pwaPlugin.spec.js b/packages/@vue/cli-plugin-pwa/__tests__/pwaPlugin.spec.js index 0f866e8c8a..c856f4c2da 100644 --- a/packages/@vue/cli-plugin-pwa/__tests__/pwaPlugin.spec.js +++ b/packages/@vue/cli-plugin-pwa/__tests__/pwaPlugin.spec.js @@ -26,6 +26,28 @@ test('pwa', async () => { expect(project.has('dist/manifest.json')).toBe(true) expect(project.has('dist/img/icons/android-chrome-512x512.png')).toBe(true) + const manifest = await project.read('dist/manifest.json') + expect(JSON.parse(manifest)).toEqual({ + name: 'pwa-build', + short_name: 'pwa-build', + theme_color: '#4DBA87', + icons: [ + { + src: './img/icons/android-chrome-192x192.png', + sizes: '192x192', + type: 'image/png' + }, + { + src: './img/icons/android-chrome-512x512.png', + sizes: '512x512', + type: 'image/png' + } + ], + start_url: './index.html', + display: 'standalone', + background_color: '#000000' + }) + // Make sure the base preload/prefetch are not affected const index = await project.read('dist/index.html') diff --git a/packages/@vue/cli-plugin-pwa/index.js b/packages/@vue/cli-plugin-pwa/index.js index 91b52f68e2..fe334758f8 100644 --- a/packages/@vue/cli-plugin-pwa/index.js +++ b/packages/@vue/cli-plugin-pwa/index.js @@ -6,6 +6,7 @@ module.exports = (api, options) => { } const name = api.service.pkg.name + const assetsPublic = api.resolve('public') const userOptions = options.pwa || {} // the pwa plugin hooks on to html-webpack-plugin @@ -13,7 +14,8 @@ module.exports = (api, options) => { webpackConfig .plugin('pwa') .use(require('./lib/HtmlPwaPlugin'), [Object.assign({ - name + name, + assetsPublic }, userOptions)]) .after('html') diff --git a/packages/@vue/cli-plugin-pwa/lib/HtmlPwaPlugin.js b/packages/@vue/cli-plugin-pwa/lib/HtmlPwaPlugin.js index 68aa476c78..0be798d2be 100644 --- a/packages/@vue/cli-plugin-pwa/lib/HtmlPwaPlugin.js +++ b/packages/@vue/cli-plugin-pwa/lib/HtmlPwaPlugin.js @@ -24,7 +24,7 @@ const defaultManifest = { "type": "image/png" } ], - start_url: '.', + start_url: './index.html', display: 'standalone', background_color: "#000000" } @@ -132,20 +132,52 @@ module.exports = class HtmlPwaPlugin { }) + // generated manifest.json compiler.hooks.emit.tapAsync(ID, (data, cb) => { const { name, + assetsPublic, themeColor, manifestPath, manifestOptions } = this.options + const publicOptions = { name, short_name: name, theme_color: themeColor } + + const manifestFilePath = path.resolve(assetsPublic, manifestPath) + let fileManifest + try { + fileManifest = JSON.parse( + fs.readFileSync(manifestFilePath).toString() + ) + + // Check the generated manifest.json (without file) is identical to the existing one + const nofileManifest = Object.assign(publicOptions, defaultManifest, manifestOptions) + const isIdentical = !Object.keys(fileManifest).find((key) => { + return ( + JSON.stringify(fileManifest[key]) !== + JSON.stringify(nofileManifest[key]) + ) + }) + + // Throw info or warn + setTimeout(() => { + if (isIdentical) { + info(`You can safely delete the manifest.json redundant file.\nFile Path: ${manifestFilePath}`) + } else { + warn(`Recommend: Use pwa.manifestOptions instead of ${manifestFilePath}`) + } + }, 1000) + } catch (err) { + fileManifest = {} + } + const outputManifest = JSON.stringify( - Object.assign(publicOptions, defaultManifest, manifestOptions) + Object.assign(publicOptions, defaultManifest, fileManifest, manifestOptions) ) data.assets[manifestPath] = { source: () => outputManifest,