@vue/cli-plugin-pwa 4.1.2 を使ってPWAを作っているWebアプリでカスタマイズしているService Workerをwebpackなどでビルドして生成されるソースマップをビルド結果にも含めたいが、将来のアップデートを待つのが良さそう
(タイトルの修飾がすごいことなってる)
やりたいこと
前提として@vue/cli-plugin-pwaはWorkboxを内部で使っている。
@vue/cli-plugin-pwaを使ってPWAを作っているWebアプリケーションでInjectManifestを使ってService Workerをカスタマイズしている時に、そのカスタマイズしているService Workerを他の仕組みでビルドして生成されるソースマップをWorkboxでのビルド結果にも含めたい。
(いつも以上に日本語をよくすべき感がある)
Service Workerを他の仕組みでビルドというのはwebpackなどを使うことを想定している。これによってService Workerでもimport ... from ...みたいにして任意のnpmパッケージを手軽に取り込めたりする。
ソースマップはbundleされて巨大になったService Workerをデバッグするときにものすごく貢献するのでWorkboxでもソースマップをビルド結果に含めたくなる。
結論
現在の@vue/cli-plugin-pwa 4.1.2だとできなさそう。
ただし上手くいかないのは内部で使われているWorkboxが^4.3.1だから。Workboxの5.0.0-rc.2だとソースマップをちゃんとビルド結果に含めてくれる。そのため今後のアップデートでソースマップ対応されることが分かった。そのWorkboxへの更新が@vue/cli-plugin-pwaにも反映されてVueのPWAでもその恩恵にあずかることができるはず。
無理やりやれるところまでやって可能性を探る
実際にPiping UIののコミットの次にした変更を実際のdiffを交えて説明も書く。
ESLInt
.eslintrc.jsで'no-console': "off"に変更しと"no-empty": "off"に変更している。これは生成されるsw.jsにconsole.logや空のブロックが含まれてESLIntでエラーしたから。ファイルをexcludeする方法を探すのもありだが可能性を探ることの本質でないので"off"にした。
@vue/cli-plugin-pwaが内部で使うWorkboxのバージョンを5.0.0-rc.2に強制固定
"preinstall": "npx npm-force-resolutions"の追加と以下の追加で実現している。実際にpackage-lock.jsonみてみると@vue/cli-plugin-pwa 4.1.2が使っていたWorkboxの4.3.1が消えていた。
code:package.json
...
"resolutions": {
"workbox-webpack-plugin": "5.0.0-rc.2"
}
...
これは以下で公開されているnpm-force-resolutionsを使って依存関係を強制的に固定している。
https://gh-card.dev/repos/rogeriochaves/npm-force-resolutions.svg https://github.com/rogeriochaves/npm-force-resolutions
vue.config.js
importWorkboxFrom: 'local'を削除している。これはimportWorkboxFromというフィールドがないのような内容のエラーメッセージが出たため消した。もしかするとWorkbox 5系ではフィールド名が変更されたりしているかもしれない。リリースされた時に調べる。
全差分
package-lock.jsonの差分は大きかったので下の差分には含んでいない。
だがnpm-force-resolutions使っているのでnpm iをするとpackage-lock.jsonも生成できる。
code:diff
diff --git a/.eslintrc.js b/.eslintrc.js
index 1ed19e6..c74168a 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -9,8 +9,9 @@ module.exports = {
'@vue/typescript'
],
rules: {
- 'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off',
- 'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off'
+ 'no-console': process.env.NODE_ENV === 'production' ? 'off' : 'off',
+ 'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off',
+ "no-empty": "off",
},
parserOptions: {
parser: '@typescript-eslint/parser'
diff --git a/package.json b/package.json
index ae30001..8432d23 100644
--- a/package.json
+++ b/package.json
@@ -15,7 +15,8 @@
"generate-sitemap": "ts-node --project scripts/tsconfig.json scripts/generate-sitemap.tsx > public/sitemap.xml",
"generate-version": "cross-var echo \"export const VERSION = \\\"$npm_package_version\\\";\" > src/version.ts",
"postinstall": "license-checker --production --json > src/licenses.json",
- "real-serve": "watch-build-serve -i=dist -i=.idea -i=./node_modules -i=.git -i=src/version.ts -i src/service-worker/dist -i public/openpgp -i src/licenses.json -i public/sitemap.xml -i public/robots.txt"
+ "real-serve": "watch-build-serve -i=dist -i=.idea -i=./node_modules -i=.git -i=src/version.ts -i src/service-worker/dist -i public/openpgp -i src/licenses.json -i public/sitemap.xml -i public/robots.txt",
+ "preinstall": "npx npm-force-resolutions"
},
"dependencies": {
"@fortawesome/fontawesome-svg-core": "^1.2.26",
@@ -89,5 +90,8 @@
"repository": {
"type": "git",
"url": "https://github.com/nwtgck/piping-ui-web"
+ },
+ "resolutions": {
+ "workbox-webpack-plugin": "5.0.0-rc.2"
}
}
diff --git a/src/service-worker/webpack.config.js b/src/service-worker/webpack.config.js
index 53cccc1..28246b3 100644
--- a/src/service-worker/webpack.config.js
+++ b/src/service-worker/webpack.config.js
@@ -2,6 +2,7 @@ const path = require('path');
module.exports = {
target: 'webworker',
+ devtool: 'source-map',
output: {
filename: 'sw.js',
path: path.resolve(__dirname, 'dist')
diff --git a/vue.config.js b/vue.config.js
index 21d870c..06afdc9 100644
--- a/vue.config.js
+++ b/vue.config.js
@@ -27,7 +27,7 @@ module.exports = {
workboxOptions: {
swSrc: './src/service-worker/dist/sw.js',
swDest: 'service-worker.js',
- importWorkboxFrom: 'local',
+ // importWorkboxFrom: 'local',
exclude: /\.map$/, '_redirects',
},
}
ビルド結果
まずビルド結果の前にWorkboxのswSrcの対象になっている./src/service-worker/dist/sw.jsとそのソースマップが以下のように配置されている。
https://gyazo.com/03b238525c363cbc624e433ddca1289a
以下がWorkboxの処理が終わったビルド結果。service-worker.js.mapが生成されていることが確認できる。
https://gyazo.com/3bae9d0962f83572b8d8fd127fd4d578
ただし以下のようにself.__WB_MANIFESTが見つからないというエラーが出て正常終了はしていなかった。だが./distは上記のように無事に生成されている。
code:エラー
Can't find self.__WB_MANIFEST in your SW source.
...
https://gyazo.com/32c706482d0f0b8cfbf34ff52608d8ff
このエラーを頑張って対処するのもありだと思うがWorkbox 5系自体もRCだし安定していない技術の上に色々載せると分かりづらいバグを踏みそうなのでここは今後のアップデートを待ちたいと思う。
これを通してWorkbox 5ならソースマップ対応もしてくれるという将来の可能性が見えたのが良かった。
おまけ
そもそもWorkboxのRCの5系で上手く行きそうだな思ったは
Account for injectManifest replacements in sourcemaps by jeffposnick · Pull Request #2239 · GoogleChrome/workboxというPRをみたり、
masterのInjectManifest: にはソースマップ関連があるのに、
このURLはpermanentでないことに注意。
4.3.1のInjectManifest: にはソースマップ関連のコードがないことを見つけたから。
だからもしかすると5系ならいけるのではないかと思い実際に試してみると上手く行った。(最後の最後でビルドのエラーができるものの)
@vue/cli-plugin-pwaにこのWorkbox 5系の対応するissue(Workbox release v5.0 · Issue #5119 · vuejs/vue-cli)がある。