Service Workerで任意のnpmパッケージをimportしたいのでwebpackを導入して実現した方法
#Service_Worker #npm #PWA
やりたいこと
Service Workerでロジックを書く機会が多くなってくると既存のnpmパッケージをimportして使いたくなる。
ここではVueと@vue/cli-plugin-pwaを使っているプロジェクトでそれを実現できたのでそれについて書く。
やりかた
以下が実際の変更箇所。
ファイル構成としては、以下のようにService Workerをbundleするためのwebpackの設定を書いた。
src/service-worker/sw.js
src/service-worker/webpack.config.js
以下が各ファイルの中身。
code:src/service-worker/sw.js
import ... from "..." // 好きにnpmのパッケージをインポートできる。
上記の実例だとimport {createReadableStreamWrapper} from '@mattiasbuelens/web-streams-adapter';をインポートしている。
以下はtarget: "webworker"になっている点に注目。
bundleされたService Workerはsrc/service-worker/dist/sw.jsに吐かれる。
code:src/service-worker/webpack.config.js
const path = require('path');
module.exports = {
target: 'webworker',
output: {
filename: 'sw.js',
path: path.resolve(__dirname, 'dist')
},
};
以下のように"build-sw"と名付けたnpmスクリプトでwebpack-cliを使ってビルドしている。
code:package.json
"scripts": {
...
"build-sw": "webpack --config src/service-worker/webpack.config.js src/service-worker/sw.js",
...
}
Vue CLIを使っているのでnpm run buildのスクリプトは上記のbuild-swを使って"build": "npm run build-sw && vue-cli-service build"のようにビルドしている。
上記でbundleされた./src/service-worker/dist/sw.jsをvue.config.jsのswSrcに指定して最終結果を作り上げる。
code:vue.config.js
...
pwa: {
workboxPluginMode: 'InjectManifest',
workboxOptions: {
swSrc: './src/service-worker/dist/sw.js',
swDest: 'service-worker.js',
importWorkboxFrom: 'local',
exclude: /\.map$/, '_redirects',
},
}
...
思い浮かぶ制限
Vue CLI内部のwebpackとService Workerをビルドするwebpackのビルドが別なので同じリソースがあっても共有されることはない。
また現在2020/1/24の@vue/cli-plugin-pwaだとWorkbox 4系が使われておりService WorkerのソースマップをswSrcから引っ張ってきてくれない。そのため巨大なbundleされたService Workerができあがってその実行時エラーがあると箇所を見つけるのが難しい可能性がある。ただ「@vue/cli-plugin-pwa 4.1.2 を使ってPWAを作っているWebアプリでカスタマイズしているService Workerをwebpackなどでビルドして生成されるソースマップをビルド結果にも含めたいが、将来のアップデートを待つのが良さそう」で検証した通り今後のバージョンアップでこの問題は解決する。