乐趣区

serviceworker用法详解

一、背景

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 的,这是不被允许的。
退出移动版