> ## Content Index
> Fetch the complete content index at: https://www.richarvin.com/llms.txt
> Use this file to discover other available public pages before exploring further.

# 如何让你的网站支持PWA？
- URL: https://www.richarvin.com/ru-he-rang-ni-de-wang-zhan-zhi-chi-pwa/
- Published: 2023-10-27T05:19:01.000Z
- Updated: 2024-05-22T02:40:44.000Z
- Author: Richarvin
- Tags: 编程技术

## 一、什么是PWA？

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

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

![](https://picture.richarvin.com/202310/xnip2023-10-29_02-27-31.png)

## 二、如何安装PWA？

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

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

### 1、创建 manifest.json（清单文件）

```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）编辑器](https://maskable.app/editor/?ref=richarvin.com)
- start\_url ：当用户从设备的应用菜单或主屏幕轻敲web应用的图标时所展示的页面
- display ：显示模式。显示模式会更改向用户显示的浏览器UI的大小，范围可以从browser（显示完整的浏览器窗口时）到fullscreen（全屏显示应用程序时）
- "dir": "ltr" 表示文本方向为从左到右 (left-to-right)，这是指示浏览器渲染文本的方向。在大多数语言中，如英语、法语、西班牙语等，文本都是从左到右排列的，所以可以使用 "ltr" 来指定文本方向。如果你的应用需要支持从右到左的语言（如阿拉伯语、希伯来语等），你可以将 "dir" 设置为 "rtl"，表示文本方向是从右到左。  
manifest.json文件一定要存放到你网站的根目录下。
[ICON批量生成器](https://icon.wuruihong.com/?ref=richarvin.com) 

### 2、配置Service worker（sw.js）

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

```javascript
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文件:

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

```

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

```javascript
    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功能的时候会非常有用：

![](https://picture.richarvin.com/202311/wx20231124-125236-2x.png)

## 三、安装和卸载 PWA Web 应用

### 安装 PWA

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

![URL 地址栏中的 PWA 安装提示](https://developer.mozilla.org/zh-CN/docs/Web/Progressive_web_apps/Guides/Installing/pwa-install.png)

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

![PWA 安装确认提示](https://developer.mozilla.org/zh-CN/docs/Web/Progressive_web_apps/Guides/Installing/installconfirm.jpg)

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

![PWA 在 MacOS 上的 Dock 中的图标](https://developer.mozilla.org/zh-CN/docs/Web/Progressive_web_apps/Guides/Installing/dock.jpg)

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

![在 Android 上安装 PWA 的示例，包括确认、主屏幕图标和离线体验](https://developer.mozilla.org/zh-CN/docs/Web/Progressive_web_apps/Guides/Installing/android_pwa.jpg)

一旦安装，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 中的应用程序设置，包含卸载链接](https://developer.mozilla.org/zh-CN/docs/Web/Progressive_web_apps/Guides/Installing/remove.jpg)

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

在 Edge 中，已安装的 PWA 会列在一个列表中，可以通过在 Edge 浏览器中访问 [edge://apps](https://blogs.windows.com/msedgedev/2022/05/18/find-and-manage-your-installed-apps-and-sites/?ref=richarvin.com) 来管理它们。在 Chrome 中，Google 应用和已安装的 PWA 的列表可以通过在 Chrome 浏览器中访问 `chrome://apps` 来查看和管理。