给所有的Web应用程序添加离线支持

原文地址:Add offline support to any Web app

最近,我参加了Angular Attack 2016 Hackathon编程马拉松活动,并且开发出了一款叫做“Let Me See”的应用,它可以帮助那些失明的人们看到世界(PS:瞬间感觉很伟大的样子…)。这款应用通过使用Ionic2(当然也有Angular2)开发而成。最重要的是我想要让这款应用是更加进步更加优秀的,所以为了得到一个更好的及时加载体验,我给它添加了支持离线缓存的功能。那么下面就让我告诉你们我是如何简单又快速地添加这项功能的。

Oh! By the way, “Let Me See” has won the Innovation prize!(哦!对了,“Let Me See”已经荣获了创新奖!)

在我们开始之前,我要假设你们已经有了一个现有的Web app应用了(PS:哈哈,够强势)。接下来我将用“Let Me See”作为例子一起来进行以下的步骤操作,并且这些步骤将适用于任何现代的单页面应用。

那就让我们开始吧,首先这里是我们的应用的一个结构截图:

你可以看到,由于应用托管在Firebase上,这是一个有一些额外Firebase配置文件的简单的Ionic2应用。

你应该注意到的是这里有一个sw-precache-config.json的文件,这个文件使用到了Service Worker Precachesw-precache)工具。

Tl;Dr: The Service Worker Precache allows us to precache all necessary resources needed by the application shell. It also generates the server worker file for us, automagically!(Service Worker Precache允许我们通过应用的shell来预先缓存所有必要的资源,它还可以自动为我们生成服务器运行文件!)

以下是sw-precache工具如何执行操作使其起作用的步骤。

首先,你必须决定是否要让其作为一个command line interface(CLI)在全局去使用这个工具:

1
$ npm install --global sw-precache

并且像这样去使用:

1
2
$ sw-precache --sw-file='www/sw.js' \
--static-file-globs='www/**/*.html'

或者加入到你的本地依赖管理中:

1
$ npm install --save-dev sw-precache

然后,我们需要提供一个sw-precache-config.json配置文件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
{
"swFile": "www/sw.js",
"staticFileGlobs": [
"www/manifest.json",
"www/**/*.css",
"www/**/*.{ttf,woff,woff2,eof}",
"www/**/*.js",
"www/**/*.html",
"www/**/*.{png,jpg,gif,svg,mp3}"
],
"handleFetch": true,
"stripPrefix": "www/",
"cacheId": "let-me-see-v1",
"maximumFileSizeToCacheInBytes": 4194304,
"ignoreUrlParametersMatching": "[/./]",
"verbose": true
}

让我来快速讲解下这其中的一些配置项的含义:

  • swFile:将生成service worker文件的路径(此配置项没有记录,请查看这个文件);

  • staticFileGlobs:一个或多个字符串匹配模式的数组。匹配到的是将会被缓存和离线使用的文件;

  • handleFetch:确定fetch事件处理程序是否包含在生成的service worker代码中;

  • cacheId:用于区分缓存的字符串;

  • maximumFileSizeToCacheInBytes:设置一个预缓存列表文件允许的最大值(点我看这里(调皮状..));

  • stripPrefix:在程序运行时从URL路径的开始处移除指定的字符串;

你可以在github repository阅读有关这些配置项的更详细的文档。

既然我们已经有了安装好的sw-precache工具,接下来就需要让它在我们的app中运行起来。因为Ionic2使用Gulp作为它的一个构建系统所以我选择用sw-precache作为Gulp的一个任务。

让我们用Gulp来创建我们的sw任务吧:

1
2
3
4
5
6
7
8
gulp.task('sw', function(callback) {
var path = require('path');
var swPrecache = require('sw-precache');
var rootDir = 'www';
var options = require('./sw-precache-config.json');
options.ignoreUrlParametersMatching = [/./];
swPrecache.write(path.join(rootDir, 'sw.js'), options, callback);
});

当构建完成后sw-precache工具能够生成service worker

1
2
3
//...
gulp.task('build:after', ['sw']);
//...

当然我们也可以选择在watch任务期间运行sw任务,这就意味着每次你在你的应用中编辑文件后service worker将会自动生成。

1
2
3
4
5
gulp.task('watch', ['clean'], function(done){
runSequence(
['sass', 'html', 'fonts', 'scripts'],
'sw',
function(){ //...

我也强烈建议你关掉handleFetch配置项,否则内容将会总是从service worker缓存中提供服务支持。

就是这样了,你已经做完了!

你现在为你的web应用添加了离线支持。你可以在here on github看到“Let Me See”自动生成service worker完整的内容。

最后很重要的是别忘了在你的index.html中注册service worker

1
2
3
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('sw.js');
}
坚持原创技术分享,您的支持将鼓励我继续创作!