如何让你的网站支持PWA?

如何让你的网站支持PWA?

一、什么是PWA?

渐进式 Web 应用(Progressive Web App,PWA)是一个使用 web 平台技术构建的应用程序,但它提供的用户体验就像一个特定平台的应用程序。它能像网站一样,通过一个代码库在多个平台和设备上运行。它也像一个特定平台的应用程序一样,可以安装在设备上,可以离线和在后台运行,并且可以与设备和其他已安装的应用程序集成。优点是增加了用户的粘性,省去了用户记忆域名的繁琐过程,在Google的大力支持下,对你网站排名SEO的优化也有很大的帮助。

虽然有以上的优点,但是很多人仍会把PWA与传统书签搞混,误以为PWA就是一个书签。那么两者到底有什么区别呢:

二、如何安装PWA?

为你的网站创建一个PWA,我们至少需要以下功能:

  • 网站必须支持HTTPS协议
  • manifest.json(清单文件)、配置文件中所要的logo图片
  • Service Worker(sw.js脚本)

1、创建 manifest.json(清单文件)

{
  "name": "HackerWeb",
  "short_name": "HackerWeb",
  "start_url": "https://www.example.com",
  "display": "standalone",
  "background_color": "#212121",
  "theme_color": "#FF0000",
  "description": "A simply readable Hacker News app.",
  "dir": "ltr",
  "lang": "en-US",
  "icons": [
    {
      "src": "path/maskable48.png",
      "sizes": "48x48",
      "type": "image/png"
    },
    {
      "src": "path/maskable72.png",
      "sizes": "72x72",
      "type": "image/png"
    },
    {
      "src": "path/maskable96.png",
      "sizes": "96x96",
      "type": "image/png",
      "purpose": "maskable"
    },
    {
      "src": "path/maskable144.png",
      "sizes": "144x144",
      "type": "image/png"
    },
    {
      "src": "path/maskable168.png",
      "sizes": "168x168",
      "type": "image/png"
    },
    {
      "src": "path/maskable192.png",
      "sizes": "192x192",
      "type": "image/png"
    }
  ],
  "screenshots": [
    {
      "src": "path/screenshot-desktop.png",
      "type": "image/png",
      "form_factor": "wide",
      "sizes": "2398x1636" 
    },
    {
      "src": "path/screenshot-mobile.png", 
      "type": "image/png",
      "sizes": "708x1300"
    }
  ]
}

配置文件必须要的参数:

基于 Chromium 的浏览器,包括 Google Chrome、Samsung Internet 和 Microsoft Edge,要求清单包含以下成员:

  • name :表示web应用的名称的字符串,因为它通常被显示给用户(例如,在其它应用程序的列表中,或者作为图标的标签)
  • icons :指定了一个对象数组,这些对象表示可以作为不同上下文的应用程序图标的图像文件。icons数组必须包含一个具有purpose属性的对象,并且该purpose属性的值必须包含maskable。
    PWA可遮盖图标(maskable)编辑器
  • start_url :当用户从设备的应用菜单或主屏幕轻敲web应用的图标时所展示的页面
  • display :显示模式。显示模式会更改向用户显示的浏览器UI的大小,范围可以从browser(显示完整的浏览器窗口时)到fullscreen(全屏显示应用程序时)
  • "dir": "ltr" 表示文本方向为从左到右 (left-to-right),这是指示浏览器渲染文本的方向。在大多数语言中,如英语、法语、西班牙语等,文本都是从左到右排列的,所以可以使用 "ltr" 来指定文本方向。如果你的应用需要支持从右到左的语言(如阿拉伯语、希伯来语等),你可以将 "dir" 设置为 "rtl",表示文本方向是从右到左。
    manifest.json文件一定要存放到你网站的根目录下。
ICON批量生成器

2、配置Service worker(sw.js)

service worker脚本与网页分开运行。通过使用service worker,我们能够为自己的web应用程序创建离线体验。该sw.js文件也要存放到你网站的根目录下。下面是一个官方sw.js代码模版:

const addResourcesToCache = async (resources) => {
  // 打开缓存
  const cache = await caches.open('v1');
  // 将资源添加到缓存中
  await cache.addAll(resources);
};

const putInCache = async (request, response) => {
  // 打开缓存
  const cache = await caches.open('v1');
  // 将请求和响应放入缓存
  await cache.put(request, response);
};

const cacheFirst = async ({ request, preloadResponsePromise, fallbackUrl }) => {
  // 首先尝试从缓存中获取资源
  const responseFromCache = await caches.match(request);
  if (responseFromCache) {
    return responseFromCache;
  }

  // 接下来尝试使用预加载的响应(如果有的话)
  const preloadResponse = await preloadResponsePromise;
  if (preloadResponse) {
    console.info('使用预加载响应', preloadResponse);
    putInCache(request, preloadResponse.clone());
    return preloadResponse;
  }

  // 接下来尝试从网络获取资源
  try {
    const responseFromNetwork = await fetch(request);
    // 响应只能使用一次
    // 我们需要保存副本以将一个副本放入缓存
    // 并提供第二个副本
    putInCache(request, responseFromNetwork.clone());
    return responseFromNetwork;
  } catch (error) {
    const fallbackResponse = await caches.match(fallbackUrl);
    if (fallbackResponse) {
      return fallbackResponse;
    }
    // 即使连备用响应也不可用,
    // 我们必须始终返回一个 Response 对象
    return new Response('网络错误发生', {
      status: 408,
      headers: { 'Content-Type': 'text/plain' },
    });
  }
};

const enableNavigationPreload = async () => {
  if (self.registration.navigationPreload) {
    // 启用导航预加载
    await self.registration.navigationPreload.enable();
  }
};

// 当服务工作者被激活时执行
self.addEventListener('activate', (event) => {
  event.waitUntil(enableNavigationPreload());
});

// 当服务工作者被安装时执行
self.addEventListener('install', (event) => {
  event.waitUntil(
    addResourcesToCache([
      '/sw-test/',
      '/sw-test/index.html',
      '/sw-test/style.css',
      '/sw-test/app.js',
      '/sw-test/image-list.js',
      '/sw-test/star-wars-logo.jpg',
      '/sw-test/gallery/bountyHunters.jpg',
      '/sw-test/gallery/myLittleVader.jpg',
      '/sw-test/gallery/snowTroopers.jpg',
    ])
  );
});

// 当发出网络请求时执行
self.addEventListener('fetch', (event) => {
  event.respondWith(
    cacheFirst({
      request: event.request,
      preloadResponsePromise: event.preloadResponse,
      fallbackUrl: '/sw-test/gallery/myLittleVader.jpg',
    })
  );
});

上述代码是一个使用 Service Worker 的缓存策略示例。它首先尝试从缓存中获取资源,如果不在缓存中,它会检查是否有预加载的响应,然后再尝试从网络获取资源。如果出现网络错误,它会回退到备用响应。在代码中,还有一些用于管理缓存的函数和事件监听器。sw.js被激活时会启用导航预加载。一旦被安装,它会将一组资源添加到缓存中,这些资源在后续的网络请求中可以用于缓存。

所以最重要的是要根据你自己网站的需求,配置相应的缓存策略,通俗的说就是你想让自己站点的哪些静态资源(图片、JS、CSS等不会经常改动的文件)缓存下来,而不需要每次用户访问的时候同样的资源还需要请求服务器,即便断网,用户仍然能够访问曾经打开加载过的资源页面,这样既加快了自己站点的打开速度,一定程度上也缓解了服务器的压力。

3、HTML文件中引入manifest.json以及注册

在HTML的<head>标签中引入manifest.json文件:

<!doctype html>
<html lang="en">
  <head>
    <link rel="manifest" href="manifest.json" />
    <!-- ... -->
  </head>
  <body></body>
</html>

在HTML的</body>标签之前引入注册的js代码(直接无脑复制粘帖即可):

    const registerServiceWorker = async () => {
  if ("serviceWorker" in navigator) {
    try {
      const registration = await navigator.serviceWorker.register("/sw.js", {
        scope: "/",
      });
      if (registration.installing) {
        console.log("Service worker installing");
      } else if (registration.waiting) {
        console.log("Service worker installed");
      } else if (registration.active) {
        console.log("Service worker active");
      }
    } catch (error) {
      console.error(`Registration failed with ${error}`);
    }
  }
};
   registerServiceWorker();

💡
到这里,你网站的PWA已经配置完毕 🎉 打开重新加载,你会发现地址栏最右侧有个电脑的小图标,而手机首次访问的时候则会询问用户是否添加应用到桌面。

浏览器开发者工具的应用选项则会显示当前网站PWA的配置信息:清单、Service workers、存储,这里在调试PWA功能的时候会非常有用:

三、安装和卸载 PWA Web 应用

安装 PWA

安装PWA 的用户界面因设备和操作系统的组合而异。在 iOS 的 Safari 上,用户界面“添加到主屏幕”会安装 PWA。其他浏览器,包括 Android 上的 Chrome,在浏览器设置菜单中包含应用程序安装命令。在桌面上的 Chrome 和 Edge 中,当用户导航到页面时,如果页面是 PWA,并且浏览器当前未安装该 PWA,URL 地址栏中将显示一个安装图标:

URL 地址栏中的 PWA 安装提示

当用户选择该图标时,浏览器会显示一个提示,询问是否要安装 PWA,如果用户接受,PWA 将被安装。

PWA 安装确认提示

一旦安装,PWA 将像操作系统上的其他应用程序一样运行。例如,在 macOS 上,图标将显示在 Dock 中,并具有与其他应用程序相同的图标选项:

PWA 在 MacOS 上的 Dock 中的图标

在大多数桌面浏览器上,安装提示位于 URL 栏中。在移动设备上,安装提示通常位于浏览器选项菜单中。无论是哪种浏览器还是操作系统,都需要确认安装。

在 Android 上安装 PWA 的示例,包括确认、主屏幕图标和离线体验

一旦安装,PWA 的行为就像其他已安装的应用程序一样:单击应用程序图标即可打开 PWA,即使用户处于离线状态也可以打开。

所有现代桌面和移动设备都支持安装。PWA 是否可以由浏览器在操作系统上安装取决于浏览器/操作系统的组合。大多数浏览器直接或在安装扩展程序后支持在所有操作系统(如 Chrome OS、MacOS、Windows、Android、Linux 等)上安装 PWA。

卸载PWA

在大多数移动操作系统上,卸载 PWA 的方法与卸载其他应用程序相同。在某些移动操作系统上,PWA 显示在管理从应用商店下载的应用程序的同一控制面板中,可以在那里卸载它们。

在 iOS 上,从 Safari 安装的 PWA 在“应用库”屏幕上列出并可搜索,但不会在“设置”下的其他已安装应用程序中列出。在 iOS 上,长按图标会显示删除书签的用户界面;从主屏幕删除图标会删除 PWA。

在某些桌面操作系统上,可以直接在已打开的 PWA 中卸载 PWA。要卸载,打开 PWA。在打开的应用程序的右上角,有一个图标,必须展开以查看更多工具。根据用于安装 PWA 的浏览器,要么有一个卸载 PWA 的链接,要么有一个打开浏览器设置页面的链接,其中包含一个卸载链接。如果有的话,可以单击下拉菜单中的卸载选项,或在浏览器选项卡中导航到应用程序设置,并点击卸载。

MS Edge 中的应用程序设置,包含卸载链接

在 Edge 中,从打开的下拉菜单中选择应用设置,会打开 MS Edge 浏览器的 edge://apps 标签页。在那里,我们会看到已安装应用程序的列表,每个应用程序都有各种选项,包括“🗑️ 卸载”。确认卸载操作。就这么简单!

在 Edge 中,已安装的 PWA 会列在一个列表中,可以通过在 Edge 浏览器中访问 edge://apps 来管理它们。在 Chrome 中,Google 应用和已安装的 PWA 的列表可以通过在 Chrome 浏览器中访问 chrome://apps 来查看和管理。