# 离线缓存

关于离线缓存,HTML5 提供一种 应用程序缓存 机制,使得基于 web 的应用程序可以离线运行。离线缓存只会下载在服务器上改变的资源。

WARNING

在此刻使用 manifest 应用程序缓存功能高度不鼓励; 它正在处于从 Web 平台中被删除的过程。请改用 Service Workers 代替。事实上,在 Firefox 44 中,当 AppCache 用于为页面提供离线支持时,控制台中现在显示一条警告消息,建议开发人员改用 Service workers 代替 (bug 1204581)。

即我们不再讨论manifest技术,只关注Service Workers

# Service Workers

在 Chrome 开启: 访问 chrome://flags 并开启 experimental-web-platform-features; 重启浏览器 (注意:有些特性在 Chrome 中没有默认开放支持)

Service Workers极大的解决了 JavaScript 单线程的痛点,通过 Web Worker,我们可以为 JavaScript 创建运行在后台的额外线程,并被多个页面共享。同时拥有拦截请求、消息推送、静默更新、地理围栏等服务,在某种程度上接近了原生 app。

TIP

点击此处 (opens new window),在浏览器上查看。

# register workers

如何使用Service Workers,首先注册:

if ('serviceWorker' in navigator) {
    //环境特性检查
    navigator.serviceWorker
        .register('/Technical-tree/sw.js', { scope: '/Technical-tree/' })
        // scope可使用的域范围,即service worker 控制的内容的子目录
        .then(function(reg) {
            // registration worked
            console.log('Registration succeeded. Scope is ' + reg.scope)
        })
        .catch(function(error) {
            // registration failed
            console.log('Registration failed with ' + error)
        })
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14

WARNING

service worker 文件的地址需要相对于 origin,且只支持httpslocalhost

# install workers

新增一个install时间监听器(ExtendableEvent.waitUntil()保障生命周期),addAll 则是需要离线的一系列文件。

this.addEventListener('install', function(event) {
    event.waitUntil(
        caches.open('v1').then(function(cache) {
            return cache.addAll([
                '/Technical-tree/code/ServiceWorkers/',
                '/Technical-tree/code/ServiceWorkers/index.html',
                '/Technical-tree/code/ServiceWorkers/app.js',
                '/Technical-tree/code/ServiceWorkers/timg.jpg'
            ])
        })
    )
})
1
2
3
4
5
6
7
8
9
10
11
12

现在我们已经将站点资源缓存了,如何在离线请求时使用这些资源: 给 service worker 添加一个 fetch 的事件监听器,接着调用 event 上的 respondWith() 方法来劫持我们的 HTTP 响应。

this.addEventListener('fetch', function(event) {
    event.respondWith(caches.match(event.request))
})
1
2
3

caches.match(event.request) 允许我们对网络请求的资源和 cache 里可获取的资源进行匹配,查看是否缓存中有相应的资源。这个匹配通过 url 和 vary header 进行,就像正常的 http 请求一样。 点击此处 (opens new window),查看 MDN 相关内容。