[关闭]
@caelumtian 2017-08-24T12:37:56.000000Z 字数 22493 阅读 993

Retrofit Your Website as a Progressive Web App

将你的网站改造为 渐进增强web应用(PWA)

英文文献翻译


There’s been a lot of buzz around Progressive Web Apps (PWAs) lately, with many people questioning whether they represent[vt. 代表] the future of the (mobile) web. I’m not going to get into the whole native app vs PWA debate[vt,n 辩论争论], but one thing is for sure — they go a long way to enhancing mobile and improving its user experience. With mobile web access destined[adj. 注定的] to surpass[vt. 超越胜过] that of all other devices combined[v.结合] by 2018, can you afford to ignore this trend?

(最近大家都在讨论渐进增强web应用(Progressive Web Apps 简称PWA),许多人质疑PWA是否能代表移动web的未来。这里我不会介入navtive app 和 PWA的争论之中,但是有件事是可以确定的-PWA在很大的长度上增强移动端提高了用户的体验。到2018年移动设备的web接入的数量注定要超过其他所有设备总量和,这种趋势是不可忽视的。)

The good news is that making a PWA is not hard. In fact, it’s quite possible to take an existing website and convert it into a PWA. And that’s exactly what I’ll be doing in this tutorial[adj. 辅导的| n. 教程] — by the time you’re finished, you’ll have a website that behaves like a native web app. It will work offline and have it’s own home screen icon.

(好消息是制作PWA程序并不是很困难。实际上,将现有的网站转换成PWA是很有可能的。在本文中,我将会介绍如何将一个网站改造成像native app一样。它可以离线工作,并且拥有自己的应用图标。)

What Are Progressive Web Apps?

什么是渐进增强web应用?

Progressive Web Apps (referred to as “PWAs”) are an exciting innovation in web technology. PWAs comprise[vt. 包含,由...组成] a mixture of technologies to make a web app function like a native mobile app. The benefits for developers and users overcome the constraints[n. 约束] imposed[vt. 强加于] by web-only and native-only solutions:

(Progressiv Web App (简称PWA)是web上一个令人兴奋的创新。PWA由一系列技术组成,用来是web应用程序更像native应用。对于开发人员和用户来说,它可以突破web和native上面的限制因素:)

  1. You only need one app developed with open, standard W3C web technologies. There’s no need to develop separate[adj. 单独的] native codebases.
    (你只需要开发一个符合W3c标准的web程序,不必开发单独的native版本。)

  2. Users can discover and try your app before installation.
    (用户可以在安装前就使用你的程序)

  3. There’s no need to use an AppStore, abide[vt. 忍受] with arcane[adj. 神秘的] rules or pay fees. Application updates occur automatically without user interaction.

(我们不在需要使用 AppStore,忍受那些难懂的规则或付费。应用程序可以自动更新,不再需要用户手动操作)

  1. Users are prompted to “install” which adds an icon to their home screen.
    (网页可以提醒用户是否在主屏幕上添加应用图标)

  2. When launched, the PWA displays an attractive splash screen.
    (当程序启动时,PWA的具有吸引力的展示效果)

  3. The browser chrome options can be modified if necessary to provide a full-screen experience.

(如果有必要,可以修改浏览器设置达到全屏浏览的效果)

  1. Essential[adj. 基本的] files are cached locally so PWAs respond faster than standard web apps (they can even be faster than native apps).

(基本的文件被缓存在本地因此PWA具有比普通web应用更快的响应速度(他们设置比native app还要快))

  1. Installation is lightweight – perhaps a few hundred KB of cached data.

(安装更加的轻量,也许只是几百KB的缓存数据)

  1. All data exchanges must occur over a secure HTTPS connection.
    (所有的数据交互必须通过安全的HTTPS协议链接)

  2. PWAs function offline and can synchronize data when the connection returns.
    (PWA处于离线状态可以在连接返回后同步数据)

It’s early days, but case studies are positive. Flipkart, India’s largest e-commerce site, experienced a 70% increase in sales conversions and trebled on-site time when they abandoned their native app for a PWA. Alibaba, the world’s largest business trading platform, experienced a similar conversion rate increase of 76%.

(现在PWA技术还有些不成熟,但是已经有了积极的案例。印度最大的商务网站Flipkart 通过将native app转换成PWA使得销售增长了70%。全球最大的交易平台Alibaba转换率也达到了70%)

Solid PWA technology support is available in Firefox, Chrome and the other Blink-based browsers. Microsoft is working on an Edge implementation. Apple remains silent although there are promising comments in the WebKit five-year plan. Fortunately, browser support is mostly irrelevant…

(PWA技术已经被支持与Firefox,Chrome和其他基于Blink内核的浏览器中。微软的Edge也在努力的实现。尽管Apple在webkit五年计划上发表了很多积极的言论,但是依然没有支持PWA。(下面这句不会了))

Progressive Web Apps are Progressive Enhancements

("渐进增强"web应用)

Your app will still run in browsers which don’t support PWA technology. The user won’t get the benefits of offline functionality but everything will continue to work as before. Given the cost-to-benefit rewards, there’s little reason not to add PWA technologies to your system.

(你的网站有可能依然运行在不支持PWA的浏览器中。这样做仅仅是让用户不能使用离线等功能,网站依然可以像网站一样正常运行。鉴于利益的汇报,我们没有理由不去将PWA技术添加到我们的网站之中。)

It’s Not Just Apps

(这不仅仅是应用程序)

Google has led the PWA movement[n. 运动] so most tutorials describe how to build a Chrome-based native-looking mobile app from the ground-up. However, you don’t need a special single-page app or have to follow material[adj. 重要的] interface design guidelines. Most websites can be PWA-ized within a few hours. That includes your WordPress or static site. Smashing Magazine announced they were running as a PWA while this article was being written!

(Google 引领了PWA运动,以至于许多教程都在讲述如何在基于Chrome的基础上从头开始构建PWA应用。然而,你并不一定需要一个单页应用或者遵循界面设计指南。大多数网站都可以在几个小时能升级到PWA。这包括你的WordPress或者静态页面。在编写本文的时候,Smashing杂志宣布,他们正在支持PWA的建设。)

Demonstration Code

(示例代码)
Demonstration code is available from https://github.com/sitepoint-editors/pwa-retrofit

(你可以在这里找到示例代码:https://github.com/sitepoint-editors/pwa-retrofit )

It provides a simple four-page website with a few images, one stylesheet and a single main JavaScript file. The site works in all modern browsers (IE10+). If the browser supports PWA technologies the user can read previously-viewed pages when they’re offline.

(demo 提供了一个带有一些图片,一个样式表和一些主要的javascrit文件的四页网站。该网站可以运行在所有的现在浏览器中(IE10+)。如果您的浏览器支持PWA,那么你可以在离线时浏览整个网站。)

To run the code, ensure Node.js is installed then start the provided web server in your terminal with:

node ./server.js [port]

(运行代码请确保Node.js环境,在终端中执行下面的命令启动服务器)

node ./server.js [port]

Open Chrome or another Blink-based browser such as Opera or Vivaldi then navigate to http://localhost:8888/ (or whichever port you specified). You can also open the Developer Tools (F12 or Cmd/Ctrl + Shift + I) to view various console messages.
(打开Chrome或者基于Blik内核的浏览器,访问 http://localhost:8888/ 来查看页面。你可以打开 Developer Tools来查看控制台输出信息。)

View the home page, and perhaps one other, then go offline by either:

(下面的方案可以帮你离线查看:)

Stopping the web server with Cmd/Ctrl + C, or
Check the Offline checkbox in the Network or Application – Service Workers tab of the Developer Tools.
(关闭 web 服务器,或者在Developer Tools的 Network或Application中点击offline复选框)

Revisit any of the pages you viewed earlier and they will still load. Visit a page you’ve not seen to be presented with a “you’re offline” page containing a list of viewable pages:

(重新访问你之前的页面,他们依然会加载。访问你没有看到过的网站,则会显示 您处于离线状态的页面,其中包含了网页列表信息。)

Connect a Device

(连接移动设备)

You can also view the demonstration page on an Android smartphone connected to your PC/Mac via USB. Open the Remote devices panel from More tools in the top-left three-dot menu.

(你也可以通过USB线将移动设备连接到PC/MAC上,来查看页面。打开浏览器 More tools选中的Remote devices面板)

Select Settings on the left and click Add Rule to forward port 8888 to localhost:8888. You can now open Chrome on the smartphone and navigate to http://localhost:8888/.
(选择左侧的设置,点击 Add rule 添加 localhost:8888。现在你可以在移动设备上打开Chrome浏览器访问 http://localhost:8888)

You can use the browser menu to “Add to Home screen”. Make a couple of visits and the browser should prompt you to “install”. Both options create a new icon on your home screen. Browse a few pages then close Chrome and disconnect your device. You can then launch the PWA Website app – you’ll see a splash screen and be able to view pages you read previously despite having no connection to the server.

(你可以使用浏览器菜单中的Add to Home screen。几次访问后,浏览器也会提醒你是否安装。上述两种方法都可以将应用程序添加到你的主屏幕。浏览几个页面后关闭Chrome断开设备链接。之后打开你的 PWA 网站,你可以看见启动屏幕并且依然能够查看之前的页面,尽管这时候你处于离线状态。)

There are three essential steps to transform your website into a Progressive Web App…

(将你的网站转换成PWA仅需要一下三个基本步骤: )

Step 1: Enable HTTPS

(步骤1:设置HTTPS)

PWAs require an HTTPS connection for reasons which will become apparent shortly. Prices and processes will differ across hosts but it’s worth the cost and effort, given that Google search is ranking secure sites higher.

(PWA需要HTTPS的支持,原因不言而喻。设置HTTPS在不同的主机上有不同的流程,但是HTTPS网站会在 Google 获得更高的 Rank 这使得一切都是值得的。)

HTTPS is not necessary for the demonstration above because Chrome permits the use of localhost or any 127.x.x.x address for testing. You can also test PWA technology on HTTP sites if you launch Chrome with the following command line flags:

--user-data-dir
--unsafety-treat-insecure-origin-as-secure

(Chrome 允许使用 localhost 或者任何 127.x.x.x 来进行HTTPS测试。你也可以在Chrome启动中添加下面的命令,来使得PWA运行在HTTP中
-- user-data-dir
-- unsafety-treat-insecure-origin-as-secure )

Step 2: Create a Web App Manifest

The web app manifest provides information about the application such as the name, description, and images which are used by the OS to configure home screen icons, splash pages and the viewport. In essence[本质上], the manifest is a single file alternative to the numerous vendor[n. 供应商]-specific icon and theme meta tags you may already have in your pages.
(提供一个web应用程序相关的信息,包括名称,描述和配置到主屏幕的图标,启动图片和viewport。实际上,manifest 文件是提供上述信息的文件。)

The manifest is a JSON text file in the root of your app. It must be served with a Content-Type: application/manifest+json or Content-Type: application/json HTTP header. The file can be called anything but has been named /manifest.json in the demonstration code:

(manifest 是一个JSON格式的文件。我们必须提供含有 Content-Type: application/manifest+json 或者 Content-Type: applicaiont/json 的HTTP请求头来时使用它。该文件可以随意起名,这里我们叫做 manifest.json )

  1. {
  2. "name" : "PWA Website",
  3. "short_name" : "PWA",
  4. "description" : "An example PWA website",
  5. "start_url" : "/",
  6. "display" : "standalone",
  7. "orientation" : "any",
  8. "background_color" : "#ACE",
  9. "theme_color" : "#ACE",
  10. "icons": [
  11. {
  12. "src" : "/images/logo/logo072.png",
  13. "sizes" : "72x72",
  14. "type" : "image/png"
  15. },
  16. {
  17. "src" : "/images/logo/logo152.png",
  18. "sizes" : "152x152",
  19. "type" : "image/png"
  20. },
  21. {
  22. "src" : "/images/logo/logo192.png",
  23. "sizes" : "192x192",
  24. "type" : "image/png"
  25. },
  26. {
  27. "src" : "/images/logo/logo256.png",
  28. "sizes" : "256x256",
  29. "type" : "image/png"
  30. },
  31. {
  32. "src" : "/images/logo/logo512.png",
  33. "sizes" : "512x512",
  34. "type" : "image/png"
  35. }
  36. ]
  37. }

A link to this file is required in the of all your pages:
(在<head>标签中需要加入下面的内容:)

  1. <link rel="manifest" href="/manifest.json">

The main manifest properties are:
(这些字段的含义如下:)

(定义图片信息的数组,包括图片URL,大小和类型。应该定义一些列图标信息。)

MDN provides a full list of Web App Manifest properties.

MDN 定义了完整的列表Web App Manifest properties

The Manifest section of Chrome’s Development Tools Application tab validates your manifest JSON and provides an “Add to homescreen” link which functions on desktop devices:

(Chrome 浏览器会监听验证你的manifest文件,并且提供add to homescreen 链接)

Create a Service Worker

Service Workers are programmable[adj. 可编程的] proxies which can intercept[vt. 拦截] and respond to network requests. They are a single JavaScript file which resides[vt. 住] in the application root.

(Service Workers 是一个用来拦截网络请求的Javascript脚本,放在应用程序根目录下即可。)

Your page JavaScript (/js/main.js in the demonstration code) can check for service worker support and register the file:

(下面这段代码(/js/main.js)用来检测当网站支持 Service Worker 后注册service-worker.js脚本)

  1. if ('serviceWorker' in navigator) {
  2. // register service worker
  3. navigator.serviceWorker.register('/service-worker.js');
  4. }

If you don’t need offline capabilities [capability n. 才能], simply create an empty /service-worker.js file – users will be prompted to install your app!
(这段话和前后文对不上关系啊?)

Service workers can be bewildering[adj. 使人混乱的] but you should be able to adapt the demonstration[n. 示范] code for your own purposes. It is a standard web worker script which the browser downloads (when possible) and runs on a separate thread. It has no access to the DOM or other page APIs but will intercept network requests triggered by page changes, asset downloads, and Ajax calls.

(Service workers 可能会让感到迷惑,你可以根据自己的目的来调整demo代码。示例代码是标准的浏览器下载脚本,它单独运行在一个线程上。该脚本无权访问DOM或其他页面的API,但是它可以在网页发生变化的时候拦截网络请求,资源下载和Ajax请求。)

This is the primary reason your site requires HTTPS. Imagine the chaos if a third-party script could inject its own service worker from another domain. It would be able to examine and modify all data exchanges between the client and server!

(Service workers也是网站需要采用HTTPS的根本原因。试想一下,如果第三方脚本可有轻易注入你的Service worker中。它就有可能窃取和篡改客户端和服务端之间的通讯信息。)

Service workers react[vt. 使反应] to three primary events: install, activate and fetch.

(Service workers 需要响应下面三个基本事件:install, activate 和 fetch)

Install Event

(注册事件)

This occurs when the application is installed. It is typically used to cache essential[adj. 基本的] files using the Cache API.

(这个事件发生在Service worker注册阶段。它通常用于使用Cache API来创建缓存,放置应用离线时所需要的资源。)

First, we’ll define some configuration variables for:

(首先,我们定义一些基础的配置:)

  1. The cache name (CACHE) and version (version). Your application can have multiple cache stores but we only require one. A version number is applied, so if we make significant changes a new cache will be used and all previously cached files are ignored.

(缓存名称(CACHE)和版本号(version) 你的应用可以有多个缓存,但我们只使用一个。因此应用版本号就很有用,当网站有重大的改变后,将使用心得缓存忽略掉之前的缓存)

  1. An offline page URL (offlineURL). This is a page which will be presented when the user is offline and attempts to load a page they have not visited before.

(离线页面URL(offlineURL) 当用户离线后视图访问之前没有访问过的页面,该页面将被显示。)

  1. An array of essential files to install which ensure the site functions offline (installFilesEssential). This should include assets such as CSS and JavaScript but I’ve also included the home page (/) and logo. You should also include variations[n. 变种] such as / and /index.html if URLs can be addressed in more than one way. Note that offlineURL is added to this array.

(一系列提供离线功能的基本文件(installFilesEssential) 这里应该提供一个包含CSS和Javascript的数组,我还向数组中加入了主页(/)和logo。你也应该加入其他的需要文件例如:/ 或者 /index.html。注意offlineURL也要加入这个数组)

  1. Optionally, an array of desirable[adj. 令人满意的] files (installFilesDesirable). These will be downloaded if possible but will not make the installation abort on failure.

(一些可选的文件(installFilesDesirable)。如果有可能,这些内容将会被下载,但不会使安装中断。)

  1. // configuration
  2. const
  3. version = '1.0.0',
  4. CACHE = version + '::PWAsite',
  5. offlineURL = '/offline/',
  6. installFilesEssential = [
  7. '/',
  8. '/manifest.json',
  9. '/css/styles.css',
  10. '/js/main.js',
  11. '/js/offlinepage.js',
  12. '/images/logo/logo152.png'
  13. ].concat(offlineURL),
  14. installFilesDesirable = [
  15. '/favicon.ico',
  16. '/images/logo/logo016.png',
  17. '/images/hero/power-pv.jpg',
  18. '/images/hero/power-lo.jpg',
  19. '/images/hero/power-hi.jpg'
  20. ];

The installStaticFiles() function adds files to the cache using the promise-based Cache API. A return value is only generated when the essential files are cached:

installStaticFiles() 函数利用异步的Cache API 来将这些文件添加到缓存。当缓存生成后返回Promise对象:

  1. // install static assets
  2. function installStaticFiles() {
  3. return caches.open(CACHE)
  4. .then(cache => {
  5. // cache desirable files
  6. cache.addAll(installFilesDesirable);
  7. // cache essential files
  8. return cache.addAll(installFilesEssential);
  9. });
  10. }

Finally, we add an install event listener. The waitUntil method ensures the service worker will not install until all enclosed code has executed. It runs installStaticFiles() then self.skipWaiting() to make the service worker active:

(最后,我们注册一个 install 监听器。我们必须提供一个waitUntil方法(参数为promise对象),当oninstall或者onactivate触发时被调用,来执行我们的函数):

  1. // application installation
  2. self.addEventListener('install', event => {
  3. console.log('service worker: install');
  4. // cache core files
  5. event.waitUntil(
  6. installStaticFiles()
  7. .then(() => self.skipWaiting())
  8. );
  9. });

Activate Event

This occurs when the service worker is activated either immediately after installation or on return. You may not require this handler but the demonstration code uses one to delete old caches when they exist:

(当Service worker安装成功后会被立刻激活该事件。你可能并不总是需要这个处理程序。下面这段代码可以用来删除旧的缓存:)

  1. // clear old caches
  2. function clearOldCaches() {
  3. return caches.keys()
  4. .then(keylist => {
  5. return Promise.all(
  6. keylist
  7. .filter(key => key !== CACHE)
  8. .map(key => caches.delete(key))
  9. );
  10. });
  11. }
  12. // application activated
  13. self.addEventListener('activate', event => {
  14. console.log('service worker: activate');
  15. // delete old caches
  16. event.waitUntil(
  17. clearOldCaches()
  18. .then(() => self.clients.claim())
  19. );
  20. });

Note the final self.clients.claim() call sets this service worker as the active worker for the site.

(注意,最后的 self.clients.claim() 将当前Service worker对象作为所有客户端的活动对象)。

Fetch Event

This occurs whenever a network request is made. It calls the respondWith() method to hijack[vt. 抢劫] GET requests and return:
(当网络产生请求后触发该事件,它通过调用respondWith() 方法来拦截GET请求并返回:)

  1. An asset from the cache

(缓存中的内容)

  1. If #1 fails, the asset is loaded from the network using the Fetch API) (unrelated to the service worker fetch event). That asset is then added to the cache.

(如果#1没有缓存,则使用Fetch API从网络加载资源(与Service worker的fetch event无关),然后将资源添加到缓存中。)

  1. If #1 and #2 fail, an appropriate[adj. 适当的] response is returned.

(如果#1,#2都失败了,则返回一个适当的结果)

  1. // application fetch network data
  2. self.addEventListener('fetch', event => {
  3. // abandon non-GET requests
  4. if (event.request.method !== 'GET') return;
  5. let url = event.request.url;
  6. event.respondWith(
  7. caches.open(CACHE)
  8. .then(cache => {
  9. return cache.match(event.request)
  10. .then(response => {
  11. if (response) {
  12. // return cached file
  13. console.log('cache fetch: ' + url);
  14. return response;
  15. }
  16. // make network request
  17. return fetch(event.request)
  18. .then(newreq => {
  19. console.log('network fetch: ' + url);
  20. if (newreq.ok) cache.put(event.request, newreq.clone());
  21. return newreq;
  22. })
  23. // app is offline
  24. .catch(() => offlineAsset(url));
  25. });
  26. })
  27. );
  28. });

The final call to offlineAsset(url) returns an appropriate response using a couple of helper functions:

(最后我们调用 offlineAsset(url) 方法返回一个适当的响应: (这句话翻译的有问题啊))

  1. // is image URL?
  2. let iExt = ['png', 'jpg', 'jpeg', 'gif', 'webp', 'bmp'].map(f => '.' + f);
  3. function isImage(url) {
  4. return iExt.reduce((ret, ext) => ret || url.endsWith(ext), false);
  5. }
  6. // return offline asset
  7. function offlineAsset(url) {
  8. if (isImage(url)) {
  9. // return image
  10. return new Response(
  11. '<svg role="img" viewBox="0 0 400 300" xmlns="http://www.w3.org/2000/svg"><title>offline</title><path d="M0 0h400v300H0z" fill="#eee" /><text x="200" y="150" text-anchor="middle" dominant-baseline="middle" font-family="sans-serif" font-size="50" fill="#ccc">offline</text></svg>',
  12. { headers: {
  13. 'Content-Type': 'image/svg+xml',
  14. 'Cache-Control': 'no-store'
  15. }}
  16. );
  17. }
  18. else {
  19. // return page
  20. return caches.match(offlineURL);
  21. }
  22. }

The offlineAsset() function checks whether the request is for an image and returns an SVG containing the text “offline”. All other requests return the offlineURL page.
(例子中,offlineAsset()函数用来检测请求是否是一个图片并且返回一个包含"offline"字段的SVG。其他请求则返回离线页面。)

The Service Worker section of Chrome’s Development Tools Application tab provides information about your workers, with errors and facilities[n. 设备] to force reload and make the browser go offline:

(Chrome开发工具提供了查看Service Worker信息的选项,包含了错误消息,重新加载工具和页面离线等内容)

The Cache Storage section lists all caches within the current scope and the cached assets they contain. You may need to click the refresh button at the bottom of the pane if when the cache is updated:

(Cache Storage 列出了当前环境下所有的缓存内容,如果缓存有更新你需要点击刷新按钮来看到他们。)

Unsurprisingly[adv. 不出意料的], the Clear storage section can delete your service worker and caches:

(同样Clear storage选项可以删除你的Service worker和缓存:)

步骤4:创建一个使用的离线页面

The offline page can be static HTML informing the user that the page they requested is not available offline. However, we can also provide a list of page URLs which are available to read.

(离线页面可以是一个静态页面来提醒用户他们访问的页面不能离线查看。同时,我们还需要提供一个可访问页面的URL列表供用户查看。)

The Cache API can be accessed within our main.js script. However, the API uses promises which fail in unsupported browsers and will cause all JavaScript to halt[vt. 停止] execution[n. 执行]. To avoid this, we’ll add code which checks whether the offline list element and the Caches API is available before loading another /js/offlinepage.js JavaScript file (which must be present in the installFilesEssential array above):

(我们可以再main.js中来使用Cache API。但是,API的异步请求失败的时候会导致浏览器停止运行。为了防止这种情况发生,我们将检测离线元素和Caches API是否可用的代码放在其他的文件中 /js/offlinepage.js(必须放在 installFiledEssential数组前))

  1. // load script to populate offline page list
  2. if (document.getElementById('cachedpagelist') && 'caches' in window) {
  3. var scr = document.createElement('script');
  4. scr.src = '/js/offlinepage.js';
  5. scr.async = 1;
  6. document.head.appendChild(scr);
  7. }

/js/offlinepage.js locates[vt. 定位|查找] the most recent cache by version name, gets a list of all URL keys, removes non-page URLs, sorts the list and appends it to the DOM node with the ID cachedpagelist:

(/js/offlinepage 通过版本名称来查找最近的缓存,URL列表,删除没有页面的URLs,对列表进行排序并添加到id为cachedpagelist的DOM节点上:)

  1. // cache name
  2. const
  3. CACHE = '::PWAsite',
  4. offlineURL = '/offline/',
  5. list = document.getElementById('cachedpagelist');
  6. // fetch all caches
  7. window.caches.keys()
  8. .then(cacheList => {
  9. // find caches by and order by most recent
  10. cacheList = cacheList
  11. .filter(cName => cName.includes(CACHE))
  12. .sort((a, b) => a - b);
  13. // open first cache
  14. caches.open(cacheList[0])
  15. .then(cache => {
  16. // fetch cached pages
  17. cache.keys()
  18. .then(reqList => {
  19. let frag = document.createDocumentFragment();
  20. reqList
  21. .map(req => req.url)
  22. .filter(req => (req.endsWith('/') || req.endsWith('.html')) && !req.endsWith(offlineURL))
  23. .sort()
  24. .forEach(req => {
  25. let
  26. li = document.createElement('li'),
  27. a = li.appendChild(document.createElement('a'));
  28. a.setAttribute('href', req);
  29. a.textContent = a.pathname;
  30. frag.appendChild(li);
  31. });
  32. if (list) list.appendChild(frag);
  33. });
  34. })
  35. });

Development Tools

If you think JavaScript debugging is tough, service workers won’t be much fun! Chrome’s Application tab of the Developer Tools provides a solid set of features and logging statements are also output to the console.
(如果你认为调试Serice Workers有困难,Chrome Development Tools中的 Application选项提供了一些列日志消息在控制台中。)

You should consider running your app in an Incognito[n. 匿名者] window during development since cached files are not retained after you close the tab.

(你应该在隐身模式下开发你的应用程序,这样可以避免文件缓存带来的影响。)

Firefox offers a JavaScript debugger accessed from the Service Workers option of the tools menu. Better facilities are promised soon.

(Firefox也提供了来自Service Workers的JavaScript调试信息,未来也会更加的完善。)

Finally, the Lighthouse extension for Chrome also provides useful information about your PWA’s implementation.

(最后Chrome 扩展程序 Lighthouse 可以提供更加丰富的PWA信息。)

PWA 的问题

Progressive Web Apps require new technologies so some caution is advised. That said, they are an enhancement of your existing website which should take no longer than a few hours and have no negative[adj. 负的] effect on unsupported browsers.
(对于渐进增强web应用的支持需要谨慎,如果改造它花了很长时间那就得不偿失了。毕竟不支持 PWA 也不会造成很大的负面影响。)
Developer opinions vary but there are several points to consider…
(这里我们也有几个问题需要考虑)

URL 隐藏

The demonstration site hides the URL bar which I would not recommend unless you have a single-URL app such as a game. The manifest options display: minimal-ui or display: browser are possibly best for most sites.
(如何隐藏地址栏我并没有演示,除非你开发了一个单页的游戏这才有必要。manifest的diplay:minimal-ui 或者 display: browser 才是适合大多数网站的。)

缓存重载

You could cache every page and asset on your site. That’s fine for small sites but would it be practical for those with thousands of pages? No one is likely to be interested in all your content and device storage limits could be exceeded. Even if you only store visited pages and assets like the demonstration, the cache could grow excessively[adv. 极度|过分].

(你可以缓存站点的每一页。这对于小型网站是有好处的,但是对于那些拥有很多页面的网站就不那么可取了。没有人会对你所有的内容感兴趣并且设备缓存是有限度的。及时你只缓存访问过的页面,缓存依旧增长的很明显)

Perhaps consider:

(你也许该考虑以下建议:)

缓存更新

The demonstration looks for assets in the cache before loading from the network. That’s great when users are offline but means they could be viewing old pages even when they’re online.
(缓存同样需要定期更新,不然用户只能看见旧的页面)

URLs for assets such as images and videos should never change so long-term caching is rarely a problem. You can ensure they remain cached for at least a year (31,536,000 seconds) with the Cache-Control HTTP header:

(对于图片和视频这种不经常变化的内容,你可以设置一个持续一年的缓存时间)

Cache-Control: max-age=31536000

Pages, CSS and script files can change more frequently so you could set a shorter expiry of 24 hours and ensure it is validated against the server version when online:

(页面,css和脚本文件有可能频繁更新,你需要设置较短的更新时间例如24小时,确保在线状态服务器对版本的验证)

Cache-Control: must-revalidate, max-age=86400

You could also consider cache-busting techniques to ensure older assets cannot be used, e.g. naming your CSS file styles-abc123.css and changing the hash on every release.

(你也可以考虑使用缓存清除技术来确定哪些不适用的旧文件,例如:命名你的CSS文件 styles-abc124.css,每个版本都修改哈希值。)

Caching can become complex so I’d recommend you read Jake Archibold’s Caching best practices & max-age gotchas.

(缓存是很复杂的这里我建议你阅读 Jake Archibold 的文章 Caching best practices & max-age gotchas)

更多的内容

如果你想了解更多,可以参考一下内容:

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注