渐进式网络应用程序

本指南继续沿用 管理输出 中的代码示例。

渐进式网络应用程序(progressive web application - PWA),是一种可以提供类似于native app(原生应用程序) 体验的 web app(网络应用程序)。PWA 可以用来做很多事。其中最重要的是,在离线(offline)时应用程序能够继续运行功能。这是通过使用名为 Service Workers 的 web 技术来实现的。

本章将重点介绍,如何为我们的应用程序添加离线体验。我们将使用名为 Workbox 的 Google 项目来实现此目的,该项目提供的工具可帮助我们更简单地为 web app 提供离线支持。

现在,我们并没有运行在离线环境下

到目前为止,我们一直是直接查看本地文件系统的输出结果。通常情况下,真正的用户是通过网络访问 web app;用户的浏览器会与一个提供所需资源(例如,.html, .js.css 文件)的 server 通讯。

我们通过搭建一个简易 server 下,测试下这种离线体验。这里使用 http-server package:npm install http-server --save-dev。还要修改 package.jsonscripts 部分,来添加一个 start script:

package.json

  1. {
  2. ...
  3. "scripts": {
  4. - "build": "webpack"
  5. + "build": "webpack",
  6. + "start": "http-server dist"
  7. },
  8. ...
  9. }

如果你之前没有操作过,先得运行命令 npm run build 来构建你的项目。然后运行命令 npm start。应该产生以下输出:

  1. > http-server dist
  2. 启动 http-serverserve 整个 dist 文件夹
  3. 到:
  4. http://xx.x.x.x:8080
  5. http://127.0.0.1:8080
  6. http://xxx.xxx.x.x:8080
  7. 按下 CTRL-C 停止服务

如果你打开浏览器访问 http://localhost:8080 (即 http://127.0.0.1),你应该会看到 webpack 应用程序被 serve 到 dist 目录。如果停止 server 然后刷新,则 webpack 应用程序不再可访问。

这就是我们为实现离线体验所需要的改变。在本章结束时,我们应该要实现的是,停止 server 然后刷新,仍然可以看到应用程序正常运行。

添加 Workbox

添加 workbox-webpack-plugin 插件,然后调整 webpack.config.js 文件:

  1. npm install workbox-webpack-plugin --save-dev

webpack.config.js

  1. const path = require('path');
  2. const HtmlWebpackPlugin = require('html-webpack-plugin');
  3. const CleanWebpackPlugin = require('clean-webpack-plugin');
  4. + const WorkboxPlugin = require('workbox-webpack-plugin');
  5. module.exports = {
  6. entry: {
  7. app: './src/index.js',
  8. print: './src/print.js'
  9. },
  10. plugins: [
  11. new CleanWebpackPlugin(['dist']),
  12. new HtmlWebpackPlugin({
  13. - title: '管理输出'
  14. + title: '渐进式网络应用程序'
  15. - })
  16. + }),
  17. + new WorkboxPlugin.GenerateSW({
  18. + // 这些选项帮助快速启用 ServiceWorkers
  19. + // 不允许遗留任何“旧的” ServiceWorkers
  20. + clientsClaim: true,
  21. + skipWaiting: true
  22. + })
  23. ],
  24. output: {
  25. filename: '[name].bundle.js',
  26. path: path.resolve(__dirname, 'dist')
  27. }
  28. };

完成这些设置,再次执行 npm run build,看下会发生什么:

  1. ...
  2. Asset Size Chunks Chunk Names
  3. app.bundle.js 545 kB 0, 1 [emitted] [big] app
  4. print.bundle.js 2.74 kB 1 [emitted] print
  5. index.html 254 bytes [emitted]
  6. precache-manifest.b5ca1c555e832d6fbf9462efd29d27eb.js 268 bytes [emitted]
  7. service-worker.js 1 kB [emitted]
  8. ...

现在你可以看到,生成了两个额外的文件:service-worker.js 和名称冗长的 precache-manifest.b5ca1c555e832d6fbf9462efd29d27eb.jsservice-worker.js 是 Service Worker 文件,precache-manifest.b5ca1c555e832d6fbf9462efd29d27eb.jsservice-worker.js 引用的文件,所以它也可以运行。你本地生成的文件可能会有所不同;但是应该会有一个 service-worker.js 文件。

所以,值得高兴的是,我们现在已经创建出一个 Service Worker。接下来该做什么?

注册 Service Worker

接下来我们注册 Service Worker,使其出场并开始表演。通过添加以下注册代码来完成此操作:

index.js

  1. import _ from 'lodash';
  2. import printMe from './print.js';
  3. + if ('serviceWorker' in navigator) {
  4. + window.addEventListener('load', () => {
  5. + navigator.serviceWorker.register('/service-worker.js').then(registration => {
  6. + console.log('SW registered: ', registration);
  7. + }).catch(registrationError => {
  8. + console.log('SW registration failed: ', registrationError);
  9. + });
  10. + });
  11. + }

再次运行 npm build build 来构建包含注册代码版本的应用程序。然后用 npm start 将构建结果 serve 到服务下。导航至 http://localhost:8080 并查看 console 控制台。应该看到:

  1. SW registered

现在来进行测试。停止 server 并刷新页面。如果浏览器能够支持 Service Worker,应该可以看到你的应用程序还在正常运行。然而,server 已经停止 serve 整个 dist 文件夹,此刻是 Service Worker 在进行 serve。

结论

你已经使用 Workbox 项目构建了一个离线应用程序。开始进入将 web app 改造为 PWA 的旅程。你现在可能想要考虑下一步做什么。这里谷歌提供的 PWA 文档中可以找到一些不错的资源。


贡献人员

EugeneHlushko EugeneHlushko chenxsan chenxsan johnnyreilly johnnyreilly