Webpack ServiceWorker插件助力PWA

PWA(渐进式网页应用)以及越来越普及。
其利用浏览器的Service Worker、Cache等功能,实现了离线缓存等近似与Native APP体验的特性。

今天盘点一下webpack对PWA的支持。其实就是在开发过程中方便用户配置、管理PWA的一些功能。大部分通过webpack plugin的形式实现。

1. SW Precache Webpack Plugin

此款插件是Google官方推荐的webpack插件,用于实现项目中对外部依赖的管理。它基于Chrome实验室研发的sw-precache模块,在百度Lavas项目中,也曾经使用过该插件作为其脚手架的基本配置。

安装

npm install --save-dev sw-precache-webpack-plugin

使用

var path = require('path');
var SWPrecacheWebpackPlugin = require('sw-precache-webpack-plugin');

const PUBLIC_PATH = 'https://www.my-project-name.com/';  // webpack needs the trailing slash for output.publicPath

module.exports = {

  entry: {
    main: path.resolve(__dirname, 'src/index'),
  },

  output: {
    path: path.resolve(__dirname, 'src/bundles/'),
    filename: '[name]-[hash].js',
    publicPath: PUBLIC_PATH,
  },

  plugins: [
    new SWPrecacheWebpackPlugin(
      {
        cacheId: 'my-project-name',
        dontCacheBustUrlsMatching: /\.\w{8}\./,
        filename: 'service-worker.js',
        minify: true,
        navigateFallback: PUBLIC_PATH + 'index.html',
        staticFileGlobsIgnorePatterns: [/\.map$/, /asset-manifest\.json$/],
      }
    ),
  ],
}

在打包后会生成 src/bundles/service-worker.js 文件,而我们只需要在项目模板中注册这个service-worker就可以了,以下是个service-worker注册的完整例子。

'use strict';

if ('serviceWorker' in navigator) {
  navigator.serviceWorker.register('./service-worker.js').then(function(reg) {
    reg.onupdatefound = function() {
      var installingWorker = reg.installing;
      installingWorker.onstatechange = function() {
        switch (installingWorker.state) {
          case 'installed':
            if (navigator.serviceWorker.controller) {
              console.log('当前内容有更新.');
            } else {
              console.log('当前正在访问离线内容!');
            }
            break;
          case 'redundant':
            console.error('重复载入!');
            break;
        }
      };
    };
  }).catch(function(e) {
    console.error('service-worker注册发生错误', e);
  });
}

详细配置项请访问sw-precache设置ChromeLab sw-precache设置

2. SW Register Webpack Plugin

在百度Lavas(V2)项目中产生的一个service-worker注册工具

安装

npm install sw-register-webpack-plugin --save-dev

使用

import SwRegisterWebpackPlugin from 'sw-register-webpack-plugin';

webpack({
    plugins: [
        new SwReginsterWebpackPlugin({
             version: 'this is a version string',
             filePath: './src/sw-register.js',
             prefix: '/some_scope',
             includes: [   //指定工程中非 html 文件也需要注册 sw 的,通常为模版文件。 需要注意的是,如果要指定非 html 文件也自动注册 sw, 该文件内容必须包含 <body></body> 标签
                 'a.html.tpl', // 文件名为 a.html.tpl 的文件,
                  /b\.html\.tpl$/, //也可以是正则,也可以是一个 callback function, 参数为待验证的每一个文件的 path
                  function (asset) {
                        return asset.endsWith('c.html.tpl')
                  }
             ],
             excludes: [], // 指定工程中符合自动注册的文件中的某一些文件可以不自动注册。
             output: '/module/sw-register.js'
        });
    ]

});

更多配置详情访问官方文档

3. Offline Plugin

最后推荐一个offline-plugin

安装

npm install offline-plugin --save-dev

使用

var OfflinePlugin = require('offline-plugin');

module.exports = {
  plugins: [
    // it's always better if OfflinePlugin is the last plugin added
    new OfflinePlugin({
       caches: ['fonts/roboto.woff'], // 'all' 或者 Object ,表明要缓存什么文件
       events: false, //布尔值。允许runtime接受来自Service Worker的消息,默认值为false
       publicPath: '/project/',
       responseStrategy: 'cache-first', // 配置响应策略
       // 不一一枚举了 ...
    })
  ]
}

在项目文件中注册

require('offline-plugin/runtime').install();


// 或者使用 ES6/Babel/TypeScript
import * as OfflinePluginRuntime from 'offline-plugin/runtime';
OfflinePluginRuntime.install();

更多设置请查看详细文档

总结

sw-precache-webpack-plugin 项目较早,也比较完备,offline-plugin 使用比较简单,特别是Runtime API 封装的功能容易理解,offline-plugin目前更新频率较高,需要持续关注。诸位可以根据喜好选择工具。

发表评论

电子邮件地址不会被公开。 必填项已用*标注