webpack入門_Progressive Web Application
Progressive Web Application
webpackの公式ドキュメントのProgressive Web Applicationを見ていきたいと思います。
まずPWA(Progressive Web Application)ですが、これはWEBアプリをネイティブアプリのように動作させる技術のようで以下のドキュメントを見れば大体わかるのかと思います。
https://developers.google.com/web/progressive-web-apps/
https://speakerdeck.com/nazonohito51/pwafalsesanpuruapuriwozuo-tutemita
既存のブラウザキャッシュとどう違うのかよく分からなかったのですが、以下のstack over flowを見てみるとPWAは組み込みのブラウザキャッシュよりも詳細な制御が可能で、読み込み時間をより短くすることができるといった感じのようです。ただ現在Progressive Web Applicationに対応しているブラウザはChromeとFirefoxのみのようなので注意が必要です。
https://stackoverflow.com/questions/35190699/whats-the-difference-between-using-the-service-worker-cache-api-and-regular-bro
PWA設定
それではwebpackのプロジェクトをPWAに対応させたいと思います。
まず、以下のコマンドでworkbox-webpack-pluginをインストールします。
npm install --save-dev workbox-webpack-plugin
それからwebpackの設定でworkbox-webpack-pluginを有効にするため、pluginsにWorkboxPlugin.GenerateSWを追加します。
<!-- 省略 -->
const WorkboxPlugin = require('workbox-webpack-plugin');
module.exports = {
<!-- 省略 -->
plugins: [
new WorkboxPlugin.GenerateSW({
// these options encourage the ServiceWorkers to get in there fast
// and not allow any straggling "old" SWs to hang around
clientsClaim: true,
skipWaiting: true
})
<!-- 省略 -->
それからこの状態でビルドをするとコンソールに以下のような出力があります。
Asset Size Chunks Chunk Names app.bundle.js 1.83 KiB 0 [emitted] app vendors~app.bundle.js 69.5 KiB 1 [emitted] vendors~app index.html 234 bytes [emitted] precache-manifest.ef740440ea3c540d2a9342f21e33ab31.js 274 bytes [emitted] service-worker.js 955 bytes [emitted] Entrypoint app = vendors~app.bundle.js app.bundle.js
service-worker.js と
precache-manifest.ef740440ea3c540d2a9342f21e33ab31.js が増えていたらPWAの設定が有効になっています。
試しにservice-worker.jsを見てみると以下のようになり、importScriptsでprecache-manifest.ef740440ea3c540d2a9342f21e33ab31.jsを参照していることが確認できます。
importScripts("https://storage.googleapis.com/workbox-cdn/releases/3.4.1/workbox-sw.js");
importScripts(
"precache-manifest.ef740440ea3c540d2a9342f21e33ab31.js"
);
workbox.skipWaiting();
workbox.clientsClaim();
/**
* The workboxSW.precacheAndRoute() method efficiently caches and responds to
* requests for URLs in the manifest.
* See https://goo.gl/S9QRab
*/
self.__precacheManifest = [].concat(self.__precacheManifest || []);
workbox.precaching.suppressWarnings();
workbox.precaching.precacheAndRoute(self.__precacheManifest, {});
次にprecache-manifest.ef740440ea3c540d2a9342f21e33ab31.jsを確認してみると以下のようにjsファイルのrevisionとurlを管理しており、これによりキャッシュ対象が決まっていることが想像できます。
self.__precacheManifest = [
{
"revision": "685e6afb118142fa5a61",
"url": "vendors~app.bundle.js"
},
{
"revision": "a374501106008a1687b12f7e5535aaa3",
"url": "index.html"
},
{
"revision": "29f3ff959afdf304a73d",
"url": "app.bundle.js"
}
];
動作確認
次にPWAの動作確認をしたいと思うのですが、serviceworkerによりバンドルファイルなどが読み込まれることが確認できれば良いので以下のような手順にしたいと思います。
- http-serverをインストール
- キャッシュさせるためhttp-serverを起動しlocalhostにアクセス
- http-serverを停止してから再度localhostにアクセス
ではまず以下のコマンドでhttp-serverをインストールします。
npm install --save-dev http-server
それから、package.jsonのscriptsを修正します。
<!-- 省略 -->
"scripts": {
"build": "webpack --config webpack.prod.js",
"start": "webpack-dev-server --open --config webpack.dev.js",
"http": "http-server dist",
"test": "echo \"Error: no test specified\" && exit 1"
},
<!-- 省略 -->
次にhttp-serverを起動しブラウザでhttp://localhost:8080/にアクセスします。
npm run http
ブラウザでの表示が確認できたら、次にhttp-serverを停止しブラウザのページをリロードします。この時開発者ツールのネットワークでバンドルファイル等がServiceWorkerから読み込まれていることが確認できます。

サービスワーカーのキャッシュを消したい場合はコンソールから以下を実行します。
navigator.serviceWorker.getRegistrations().then(function(registrations) {
for(let registration of registrations) {
registration.unregister();
}
});
caches.keys().then(function(keys) {
var promises = [];
keys.forEach(function(cacheName) {
if (cacheName) {
promises.push(caches.delete(cacheName));
}
});
});