这个两部分的系列文章是对离线 Web 开发的简单介绍。 使 Web 应用程序在离线状态下执行某些操作非常棘手,需要很多东西到位并正常运行。 我们将从高层次概述所有这些部分,并提供工作示例。 这篇文章是一个概述,但整个过程中列出了许多更详细的资源。
文章系列
- 设置(您当前位置)
- 实现
基本方法
我将大量使用 JavaScript 的 async/await 语法。 它在所有主要浏览器和 Node 中都受支持,并且极大地简化了基于 Promise 的代码。 上面的链接很好地解释了 async,但简而言之,它们允许您解析 Promise,并使用 await
直接在代码中访问其值,而不是调用 .then
并在回调中访问值,这通常会导致可怕的“向右漂移”。
我们正在构建什么?
我们将扩展现有的 booklist 项目,以将当前用户的书籍同步到 IndexedDB,并创建一个简化的离线页面,即使用户没有网络连接也能显示。
从 Service Worker 开始
离线开发所需的唯一不可协商的事情是 Service Worker。 Service Worker 是一个后台进程,除了其他功能外,还可以拦截网络请求;重定向它们;通过返回缓存的响应来短路它们;或者像往常一样执行它们并对响应执行自定义操作,例如缓存。
基本缓存
您使用 Service Worker 执行的第一项、最基本但影响最大的操作可能是缓存应用程序的资源。 Service Worker 及其使用的缓存是极其底层的原语;一切都必须手动操作。 为了正确缓存您的资源,您需要获取并将它们添加到缓存中,但随后您还需要跟踪这些资源的变化。 您需要跟踪它们何时更改,删除先前版本,然后获取并更新新版本。
在实践中,这意味着您的 Service Worker 代码需要作为构建步骤的一部分生成,该步骤对您的文件进行哈希处理,并生成一个足够智能的文件来记录这些版本之间的更改,并在需要时更新缓存。
抽象来救援
这是极其繁琐且容易出错的代码,您可能永远不想自己编写它。 幸运的是,一些聪明人编写了抽象来提供帮助,即 Google 的优秀人员编写的 sw-precache 和 sw-toolbox。 请注意,Google 后来弃用了这些工具,转而支持更新的 Workbox。 我还没有迁移我的代码,因为 sw-*
运行良好,但无论如何,想法都是一样的,而且我听说转换很容易。 值得一提的是,sw-precache 目前每天大约有 30,000 次下载,因此它仍然被广泛使用。
你好世界,sw-precache
让我们直接开始。 我们正在使用 webpack,就像 webpack 一样,有一个插件,所以让我们先看看它。
// inside your webpack config
new SWPrecacheWebpackPlugin({
mergeStaticsConfig: true,
filename: "service-worker.js",
staticFileGlobs: [ //static resources to cache
"static/bootstrap/css/bootstrap-booklist-build.css",
...
],
ignoreUrlParametersMatching: /./,
stripPrefixMulti: { //any paths that need adjusting
"static/": "react-redux/static/",
...
},
...
})
默认情况下,webpack 生成的所有捆绑包都将被预缓存。 我们还在 staticFileGlobs
属性中手动提供了一些我想缓存的静态资源的路径,并且我正在调整 stripPrefixMulti
中的一些路径。
// inside your webpack config
const getCache = ({ name, pattern, expires, maxEntries }) => ({
urlPattern: pattern,
handler: "cacheFirst",
options: {
cache: {
maxEntries: maxEntries || 500,
name: name,
maxAgeSeconds: expires || 60 * 60 * 24 * 365 * 2 //2 years
},
successResponses: /0|[123].*/
}
});
new SWPrecacheWebpackPlugin({
...
runtimeCaching: [ //pulls in sw-toolbox and caches dynamically based on a pattern
getCache({ pattern: /^https:\/\/images-na.ssl-images-amazon.com/, name: "amazon-images1" }),
getCache({ pattern: /book\/searchBooks/, name: "book-search", expires: 60 * 7 }), //7 minutes
...
]
})
将 runtimeCaching
部分添加到我们的 SWPrecacheWebpackPlugin
中会引入 sw-toolbox
,并允许我们根据需要动态缓存与特定模式匹配的 URL——getCache
有助于将样板代码保持在最低限度。
你好世界,sw-toolbox
生成的整个 Service Worker 文件非常大,但让我们只看一小部分,即上面动态缓存之一。
toolbox.router.get(/^https:\/\/images-na.ssl-images-amazon.com/, toolbox.cacheFirst, {
cache: { maxEntries: 500, name: "amazon-images1", maxAgeSeconds: 63072000 },
successResponses: /0|[123].*/
});
sw-toolbox
为我们提供了一个很好的高级路由器对象,我们可以使用它以 MVC 样式挂接到各种 URL 请求。 我们将使用它来很快设置离线功能。
不要忘记注册 Service Worker
当然,上面生成的 Service Worker 文件本身的存在没有任何用处;它需要注册。 代码如下所示,但请确保将其放在 onload
监听器或其他保证在页面加载后运行的地方。
if ("serviceWorker" in navigator) {
navigator.serviceWorker.register("/service-worker.js");
}
就是这样! 我们让一个基本的 Service Worker 运行起来,它缓存了我们的应用程序资源。 请继续关注明天,我们将扩展它以支持离线功能。
文章系列
- 设置(您当前位置)
- 实现
Service Worker 实际上只在 Chrome 和 Firefox 中得到支持;IE 和 Safari 不支持它们。 离线应用程序的良好跨浏览器解决方案还有很长的路要走。
确实如此,令人遗憾的是,尽管 Apple 据称已经开始开发它们。 希望我们很快就能在 iOS 上使用它们。
嗨,我尝试在 Google 上搜索“JavaScript 向右漂移”,但没有找到。 你能详细说明一下吗?
它有很多名称 :)
回调地狱、向右漂移、厄运金字塔等
http://callbackhell.com/