3

一、背景

taro框架转的h5,想在无网络状态下可以控制展示给用户的界面,使用客户端离线缓存可以达到目的,并且可以将静态资源进行缓存,从而减少白屏时间,加快页面相应速度。

二、service worker简要介绍:

service worker是一段脚本,在后台运行。作为一个独立的线程,不会对页面造成阻塞。本质上充当Web应用程序与浏览器之间的代理服务器。native app可以做到离线使用、消息推送、后台自动更新,service worker的出现是正是为了使得web app也可以具有类似的能力。在线上必须在 HTTPS 环境下才能工作,或者本地localhost域名也是可以的。

三、使用方法

第一步选择npm包,我用的是sw-precache-webpack-plugin这个包,基于webpack的插件,操作简单使用方便,详情请看文档
然后进行基于webpack的配置,下面例子是taro框架h5部分的配置内容

h5: {
    publicPath: '/',
    staticDirectory: 'static',
    webpackChain(chain, webpack) {
        chain.plugin('sw')
            .use(require('sw-precache-webpack-plugin'), [{
                cacheId: 'name',
                filename: 'service-worker.js',
                filepath: path.resolve(__dirname, '../src/service-worker.js'),
                // importScripts: [],
                // 需缓存的文件配置, 需动态缓存的放到runtimeCaching中处理
                staticFileGlobs: [],
                mergeStaticsConfig: true,
                minify: true,
                verbose: true,
                runTimeCaching: [
                    // 页面动态文件
                    {
                        urlPattern: /pages\/.*/,
                        handler: 'networkFirst'
                    },
                    {
                        urlPattern: /api\/.*/,
                        handler: 'networkFirst'
                    }
                ]
            }]
        );
    },
    module: {
        postcss: {
            autoprefixer: {
                enable: true
            }
        }
    }
}

ok,现在已经配置完了,下一步只要在入口文件里注册service-worker就行啦,我是在HTML里加的,代码如下:

<script>
(function () {
if ('serviceWorker' in navigator) {
    navigator.serviceWorker.register('./service-worker.js').then(function (registration) {
        // 注册成功
        console.log('ServiceWorker registration successful with scope: ', registration.scope);
    }).catch(function (err) {
        // 注册失败
        console.log('ServiceWorker registration failed: ', err);
    });
}
})();
</script>

大功告成,现在可以在本地调试了,本地如果启动了webpack-dev-server,则需要:webpack添加配置:

module.exports = {
devServer: {
    setup: function (app) {
        app.get('/service-worker.js', function (req, res) {
            res.set({ 'Content-Type': 'application/javascript; charset=utf-8' });
            res.send(fs.readFileSync('build/service-worker.js'));
        });
    }
}
}

此时访问localhost就可以启用service-worker啦,如果配置了这些内容service-worker还没有注册成功的话,可能的原因如下:

  1. 你没有在 HTTPS 或localhost下运行你的项目。
  2. service worker文件的地址没有写对— 需要相对于 origin , 而不是 app 的根目录。在我们的例子例, service worker 是在 https://mdn.github.io/sw-test...,app的根目录是 https://mdn.github.io/sw-test/。应该写成 /sw-test/sw.js 而非 /sw.js.
  3. service worker 在不同的 origin 而不是你的app的,这是不被允许的。

lvjiajiajia
197 声望6 粉丝

oh~