これまで、このドキュメントではプレキャッシュに重点を置き、ビルドツール generateSW
と injectManifest
に重点的に触れてきました。Service Worker にプレキャッシュ ロジックを含めるべき理由はたくさんありますが、Workbox を使用するのにプレキャッシュを使用する必要はありません。
プロジェクトでランタイム キャッシュのみが必要な場合や、Web push など、よりクリーンな方法で Service Worker API を統合したい場合があります。この記事では、Workbox のビルドツールが不要なケースについて説明します。
バンドラを使用する場合
Bundler はウェブ開発の分野では目覚ましく、お客様のプロジェクトで使われている可能性が高いと言えます。この場合、何も事前キャッシュしない場合はバンドラ プラグイン(workbox-webpack-plugin
など)を使用する必要はありません。Service Worker は、アプリケーションの別のエントリ ポイントとして扱われます。
プロジェクトのソース ディレクトリのルートに Service Worker を作成し、アプリケーションに必要な Workbox モジュールを使用します。次の例では、ナビゲーションと画像アセット リクエストのキャッシュ戦略を別々の Cache
インスタンスで設定する、プレキャッシュを使用しない例を示します。
// sw.js
import {NetworkFirst, CacheFirst} from 'workbox-strategies';
import {registerRoute, NavigationRoute, Route} from 'workbox-routing';
const navigationRoute = new NavigationRoute(new NetworkFirst({
cacheName: 'navigations'
}));
const imageAssetRoute = new Route(({request}) => {
return request.destination === 'image';
}, new CacheFirst({
cacheName: 'image-assets'
}));
registerRoute(navigationRoute);
registerRoute(imageAssetRoute);
ここからは、選択したバンドラのエントリ ポイントとして、この Service Worker を指定するだけです。以下に、いくつかの一般的なバンドラでこれを行う方法の例を示します。
Webpack
webpack は、entry
構成でエントリ ポイントを受け入れます。この方法を使用する場合は、次の点に注意してください。
- Service Worker のスコープを可能な限り広くするには、出力ディレクトリのルートに出力されるようにする必要があります。
- Service Worker を更新すると新しいハッシュが生成され、ウェブサイトに複数の Service Worker がデプロイされる可能性があるため、Service Worker のバージョニングはおすすめしません。
上記の条件を満たすために、関数を output.filename
に渡すことができます。この関数は、処理中の現在のエントリ ポイントが Service Worker のエントリ ポイントであるかどうかを確認します。それ以外の場合、バージョニングされたファイルは通常の宛先に書き込まれます。
// webpack.config.js
import process from 'process';
const isProd = process.env.NODE_ENV === 'production';
export default {
mode: isProd ? 'production' : 'development',
context: process.cwd(),
entry: {
// Service worker entry point:
sw: './src/sw.js',
// Application entry point:
app: './src/index.js'
},
output: {
filename: ({runtime}) => {
// Check if the current filename is for the service worker:
if (runtime === 'sw') {
// Output a service worker in the root of the dist directory
// Also, ensure the output file name doesn't have a hash in it
return '[name].js';
}
// Otherwise, output files as normal
return 'js/[name].[contenthash:8].js';
},
path: './dist',
publicPath: '/',
clean: true
}
};
ロールアップ
Rollup も webpack と似ています。ただし、複数のエントリ ポイントが、配列でエクスポートされる個別の構成オブジェクトとして指定されます。
// rollup.config.js
import { nodeResolve } from '@rollup/plugin-node-resolve';
import replace from '@rollup/plugin-replace';
// Plugins common to both entry points
const plugins = [
nodeResolve(),
];
export default [
// Application entry point
{
input: './src/index.js',
output: {
dir: './dist/js',
format: 'esm'
},
plugins
},
// Service worker entry point
{
input: './src/sw.js',
output: {
file: './dist/sw.js',
format: 'iife'
},
plugins: [
...plugins,
// This @rollup/plugin-replace instance replaces process.env.NODE_ENV
// statements in the Workbox libraries to match your current environment.
// This changes whether logging is enabled ('development') or disabled ('production').
replace({
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV || 'production')
})
]
}
];
ESbuild
esbuild には、わかりやすいコマンドライン インターフェースが用意されています。
npx esbuild ./src/sw.js --bundle --minify --outfile=./dist/sw.js
esbuild は、process.env.NODE_ENV をデフォルトで「development」または圧縮が有効になっている場合は「production」に置き換えます。
workbox-sw
を使用してバンドラを使用しない場合
プロジェクトでバンドラを使用しない場合もあります。workbox-sw
は、Service Worker 内の CDN から Workbox ランタイムを読み込むことができます。importScripts
でインポートした場合は、ビルドステップは必要ありません。
// sw.js
// Imports Workbox from the CDN. Note that "6.2.0" of the URL
// is the version of the Workbox runtime.
importScripts('https://storage.googleapis.com/workbox-cdn/releases/6.2.0/workbox-sw.js');
const navigationRoute = new workbox.routing.NavigationRoute(new workbox.strategies.NetworkFirst({
cacheName: 'navigations'
}));
const imageAssetRoute = new workbox.routing.Route(({request}) => {
return request.destination === 'image';
}, new workbox.strategies.CacheFirst({
cacheName: 'image-assets'
}));
workbox.routing.registerRoute(navigationRoute);
workbox.routing.registerRoute(staticAssetRoute);
CDN から Workbox ランタイムを読み込む見込みがあまりないと思われる場合は、ローカル URL で workbox-sw
を使用することができます。
まとめ
プレキャッシュを使用せずに Workbox を使用する方法を理解したところで、特定のバンドラやビルドツールに縛られることはなくなりました。これにより、Workbox のランタイム キャッシュ コードの一部を使用して、Service Worker を柔軟に作成できます。