---
# System prepended metadata

title: '[Update](https://web.dev/learn/pwa/update/) 更新'
tags: [PWA]

---

###### tags: `PWA` 

# [Update](https://web.dev/learn/pwa/update/) 更新


Chances are your PWA needs updating. This chapter gives you the tools to update different parts of your PWA, from assets to metadata.
您的 PWA 可能需要更新。本章為您提供了更新 PWA 不同部分（從資產到元數據）的工具。

You have published your PWA: some users use it from the browser, others install it on their devices. When you update the app, it's important to apply best practices to avoid pitfalls.

你已經發布了你的 PWA：一些用戶通過瀏覽器使用它，其他人將它安裝在他們的設備上。更新應用程序時，應用最佳實踐以避免陷阱很重要。

You may update:
您可以更新：

* App data.
* Assets already cached in devices.
* The service worker file, or its dependencies.
* Manifest metadata.

* 應用程序數據。
* 資產已緩存在設備中。
* 服務工作者文件或其依賴項。
* 清單元數據

Let's check out the best practices for each of these elements.
讓我們看看每個元素的最佳實踐。

## Updating data  更新數據

To update data, such as that stored in IndexedDB, you can use tools such as Fetch, WebRTC, or WebSockets API. If your app supports any offline features, remember to keep the data that supports the features updated too.

要更新數據（例如存儲在 IndexedDB 中的數據），您可以使用 Fetch、WebRTC 或 WebSockets API 等工具。如果您的應用程序支持任何離線功能，請記住也要更新支持這些功能的數據。

On compatible browsers, there are options to sync data, not only when the user opens the PWA but also in the background. These options are:

在兼容的瀏覽器上，有同步數據的選項，不僅在用戶打開 PWA 時，而且在後台。這些選項是：

* [Background synchronization](https://developer.mozilla.org/en-US/docs/Web/API/Background_Synchronization_API): saves requests that failed and retries them using sync from the service worker.

* [Web periodic background sync](https://developer.mozilla.org/en-US/docs/Web/API/Web_Periodic_Background_Synchronization_API): syncs data periodically in the background, at specific times, allowing the app to provide updated data even if the user hasn't opened the app yet.

* [Background Fetch](https://developer.mozilla.org/en-US/docs/Web/API/Background_Fetch_API): downloads large files, even when the PWA is closed.

* [Web push](https://developer.mozilla.org/zh-CN/docs/Web/API/Push_API): sends a message from the server that wakes up the service worker and notifies the user. This is commonly called a 'push notification'. This API requires the user's permission.

* 後台同步：保存失敗的請求並使用 service worker 的同步重試它們。
* Web 定期後台同步：在特定時間在後台定期同步數據，即使用戶尚未打開應用程序，應用程序也可以提供更新的數據。
* Background Fetch：下載大文件，即使 PWA 關閉也是如此。
* Web 推送：從服務器發送一條消息，喚醒 Service Worker 並通知用戶。這通常稱為“推送通知”。此 API 需要用戶的許可。


All these APIs are executed from the service worker context. They are currently available only on Chromium-based browsers, on Android, and desktop operating systems. When you use one of these APIs, you can run code in the service worker thread; for example, to download data from your server and update your IndexedDB data.

所有這些 API 都是從 service worker 上下文中執行的。它們目前僅在基於 Chromium 的瀏覽器、Android 和桌面操作系統上可用。當您使用這些 API 之一時，您可以在服務工作者線程中運行代碼；例如，從您的服務器下載數據並更新您的 IndexedDB 數據。

<div style="background-color:#D2DEF9;padding:1rem;line-height:1.9;margin-bottom:1rem">

The Web Push API is the only API to notify the user from the background and its <kbd>push </kbd>  message can include a small amount of data: it can carry a payload of up to around 2KB.
    
</div>

<div style="background-color:#D2DEF9;padding:1rem;line-height:1.9;margin-bottom:1rem">

Web Push API 是唯一從後台通知用戶的 API，其推送消息可以包含少量數據：它可以攜帶最大約 2KB 的負載。
    
</div>

## Updating assets 更新資產
Updating assets includes any changes to files you use to render the app's interface, such as HTML, CSS, JavaScript, and images. For example, a change in your app's logic, an image that is part of your interface, or a CSS stylesheet.

更新資產包括對用於呈現應用程序界面的文件的任何更改，例如 HTML、CSS、JavaScript 和圖像。例如，應用程序邏輯的更改、作為界面一部分的圖像或 CSS 樣式表。

## Update patterns 更新模式

Here are some common patterns to handle app updates, but you can always customize the process to your own needs:

以下是處理應用程序更新的一些常見模式，但您始終可以根據自己的需要自定義流程：

* Full update: every change, even a minor one, triggers the replacement of the entire cache content. This pattern mimics how device-specific apps handle updates, and it will consume more bandwidth and will take more time.

* Changed assets update: only the assets that have changed since the last update get replaced in cache. It is often implemented using a library such as [Workbox](https://web.dev/learn/pwa/workbox/). It involves creating a list of cached files, a hash representation of the file, and timestamps. With this information, the service worker compares this list with the cached assets and decides which assets to update.

* Individual assets update: each asset is updated individually when it changes. The stale while revalidate strategy described in the Serving chapter is an example of updating assets individually.


* 完全更新：每次更改，即使是很小的更改，都會觸發整個緩存內容的替換。這種模式模仿設備特定應用程序處理更新的方式，它會消耗更多帶寬並花費更多時間。


* 已更改的資產更新：只有自上次更新以來已更改的資產才會在緩存中被替換。它通常使用諸如 Workbox 之類的庫來實現。它涉及創建緩存文件列表、文件的哈希表示和時間戳。有了這些信息，服務人員將這個列表與緩存的資產進行比較，並決定更新哪些資產。 

* 單個資產更新：每個資產在更改時單獨更新。服務章節中描述的陳舊而重新驗證策略是單獨更新資產的示例。

## When to update 何時更新

Another good practice is to find a good time to check for updates and apply them. Here are some options:
另一個好的做法是找一個合適的時間來檢查更新並應用它們。以下是一些選項：

* When the service worker wakes up. There is no event to listen for this moment, but the browser will execute any code in the service worker's global scope when it wakes up.

* In the main window context of your PWA, after the browser loaded the page, to avoid making the app load slower.

* When background events are triggered, such as when your PWA receives a push notification or a background sync fires. You can update your cache then and your users will have the asset's new version the next time they open the app.

* 當 service worker 醒來時。這一刻沒有事件可監聽，但瀏覽器在喚醒時會執行 service worker 全局範圍內的任何代碼。

* 在 PWA 的主窗口上下文中，在瀏覽器加載頁面後，避免使應用加載速度變慢。


* 當觸發後台事件時，例如當您的 PWA 收到推送通知或觸發後台同步時。然後您可以更新緩存，您的用戶將在下次打開應用程序時獲得該資產的新版本。



<div style="padding:1rem;background-color:#fff5e3;">
    


<div style="display:flex">
    
:warning:
       <p style="color:#c34900;margin-top:-1.5em">
       Warning
       </p> 
</div>
    
<p style="color:#c34900;">When checking for updates, make sure you don't interrupt the loading process and impact your app's performance. Do not wait for an update check before rendering the app as it will harm your user experience and reflect on your core web vitals. If you need to update part of your app frequently, use the stale while revalidate caching strategy.
</p>

</div>

<div style="padding:1rem;background-color:#fff5e3;margin-top:1em">
    


<div style="display:flex">
    
:warning:
       <p style="color:#c34900;margin-top:-1.5em">
       Warning
       </p> 
</div>
    
<p style="color:#c34900;">檢查更新時，請確保您不會中斷加載過程並影響應用的性能。不要在呈現應用程序之前等待更新檢查，因為這會損害您的用戶體驗並反映您的核心網絡生命力。如果您需要經常更新應用程序的一部分，請使用陳舊的同時重新驗證緩存策略。
</p>

</div>


## Live updates 在線更新

You can also choose whether to apply an update when the app is open (live) or closed. With the app closed approach, even though the app has downloaded new assets, it won't make any changes and will use the new versions on the next load.
您還可以選擇是否在應用程序打開（實時）或關閉時應用更新。使用關閉應用程序的方法，即使應用程序下載了新資產，它也不會進行任何更改，並將在下一次加載時使用新版本。


A live update means as soon as the asset is updated in the cache, your PWA replaces the asset in the current load. It is a complex task not covered in this course. Some tools that help to implement this update are [livereload-js](https://www.npmjs.com/package/livereload-js) and CSS asset update [CSSStyleSheet.replace() API](https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleSheet/replace).

實時更新意味著一旦資產在緩存中更新，您的 PWA 就會替換當前負載中的資產。這是本課程未涵蓋的複雜任務。一些有助於實現此更新的工具是 livereload-js 和 CSS 資產更新 CSSStyleSheet.replace() API。

## Updating the service worker 更新服務工作者

The browser triggers an update algorithm when your service worker or its dependencies change. The browser detects updates using a byte-by-byte comparison between the cached files and the resources coming from the network.

當您的 service worker 或其依賴項發生變化時，瀏覽器會觸發更新算法。瀏覽器使用緩存文件和來自網絡的資源之間的逐字節比較來檢測更新。

Then the browser tries to install the new version of the service worker, and the new service worker will be in the waiting state, as described in the [Service workers chapter](https://web.dev/learn/pwa/service-workers/#updating-a-service-worker). The new installation will run the <kbd>install </kbd> event for the new service worker. If you are caching assets in that event handler, assets will also be re-cached.

然後瀏覽器嘗試安裝新版本的 service worker，新的 service worker 將處於等待狀態，如 Service workers 章節所述。新安裝將為新服務工作者運行安裝事件。如果您在該事件處理程序中緩存資產，資產也將被重新緩存。

<div style="padding:1rem;background-color:#fce8e8;color:#a50e0e;">
    


<div style="display:flex">
    
:warning:
       <p style="color:#a50e0e;margin-top:-1.5em">
       Caution警告
       </p> 
</div>
    
<p style="">
    
If you delete or rename your service worker file, the browser won't remove the previously registered service worker from its clients. To completely remove a service worker, you need to use the [getRegistrations()](https://developer.mozilla.org/en-US/docs/Web/API/ServiceWorkerContainer/getRegistrations) and the [unregister()](https://developer.mozilla.org/zh-CN/docs/Web/API/ServiceWorkerRegistration/unregister) methods.
</p>

</div>

<div style="padding:1rem;background-color:#fce8e8;color:#a50e0e;margin-top:1rem">
    


<div style="display:flex;">
    
:warning:
       <p style="color:#a50e0e;margin-top:-1.5em">
       Caution警告
       </p> 
</div>
    
<p style="">
    
如果您刪除或重命名您的 service worker 文件，瀏覽器不會從其客戶端中刪除之前註冊的 service worker。要完全刪除服務工作者，您需要使用 getRegistrations() 和 unregister() 方法。
</p>

</div>

<div style="background-color:#D2DEF9;padding:1rem;line-height:1.9;margin-top:1rem">

Installing a new service worker version doesn't automatically remove previously cached assets. You should explicitly delete assets you no longer need.
    
</div>

<div style="background-color:#D2DEF9;padding:1rem;line-height:1.9;margin-top:1rem">

安裝新的 service worker 版本不會自動刪除以前緩存的資產。您應該明確刪除不再需要的資產。
    
</div>

## Detecting service worker changes 檢測 service worker 的變化

To detect that a new service worker is ready and installed, we use the <kbd> updatefound </kbd> event from the service worker registration. This event is fired when the new service worker starts installing. We need to wait for its state to change to <kbd> installed </kbd> with the <kbd> statechange </kbd> event; see the following:

為了檢測新的 service worker 是否準備就緒並安裝，我們使用 service worker 註冊中的 updatefound 事件。當新的 service worker 開始安裝時會觸發此事件。我們需要等待它的狀態通過 statechange 事件變為已安裝；請參閱以下內容：

```
async function detectSWUpdate() {
  const registration = await navigator.serviceWorker.ready;

  registration.addEventListener("updatefound", event => {
    const newSW = registration.installing;
    newSW.addEventListener("statechange", event => {
      if (newSW.state == "installed") {
         // New service worker is installed, but waiting activation
      }
    });
  })
}
```

## Force override 強制覆蓋

The new service worker will be installed but waiting for activation by default. The wait prevents the new service worker from taking over old clients that might not be compatible with the new version.

新的 service worker 將被安裝，但默認情況下等待激活。等待會阻止新的 service worker 接管可能與新版本不兼容的舊客戶端。

Even though it is not recommended, the new service worker can skip that waiting period and start the activation immediately.

即使不推薦，新的 service worker 也可以跳過等待期並立即開始激活。


<div style="padding:1rem;background-color:#fce8e8;color:#a50e0e;margin-bottom:1rem">
    


<div style="display:flex">
    
:warning:
       <p style="color:#a50e0e;margin-top:-1.5em">
       Caution警告
       </p> 
</div>
    
<p style="color:#a50e0e;">

<kbd>skipWaiting() </kbd>means that your new service worker is probably controlling pages that were loaded with an older version. This means some of your page's fetches will have been handled by your old service worker, but your new service worker will be handling subsequent fetches. If this might prevent your app from working, don't use <kbd>skipWaiting() </kbd>. This warning comes from [service worker lifecycle](https://web.dev/service-worker-lifecycle/). Check out the article for more best practice advice.
</p>

</div>

<div style="padding:1rem;background-color:#fce8e8;color:#a50e0e;margin-bottom:1rem">
    


<div style="display:flex">
    
:warning:
       <p style="color:#a50e0e;margin-top:-1.5em">
       Caution警告
       </p> 
</div>
    
<p style="color:#a50e0e;">

skipWaiting() 意味著你的新 service worker 可能正在控制加載了舊版本的頁面。這意味著您的某些頁面抓取將由您的舊服務工作者處理，但您的新服務工作者將處理後續抓取。如果這可能會阻止您的應用程序運行，請不要使用 skipWaiting()。此警告來自服務工作者生命週期。查看文章以獲取更多最佳實踐建議。
</p>

</div>


```
self.addEventListener("install", event => {
   // forces a service worker to activate immediately
   self.skipWaiting();
  });

self.addEventListener("activate", event => {
  // when this SW becomes activated, we claim all the opened clients
  // they can be standalone PWA windows or browser tabs
  event.waitUntil(clients.claim());
});
```

The <kbd> controllerchange </kbd> event fires when the service worker controlling the current page changes. For example, a new worker has skipped waiting and become the new active worker.

controllerchange 事件在控制當前頁面的 service worker 發生變化時觸發。例如，一個新的工作人員跳過等待成為新的活躍工作人員。

```
navigator.serviceWorker.addEventListener("controllerchange", event => {
   // The service worker controller has changed
 });
```

## Updating metadata  更新元數據

You can also update your app's metadata, which is mainly set in the [web app manifest](https://web.dev/learn/pwa/web-app-manifest/). For example, update its icon, name, or start URL, or you can add a new feature such as [app shortcuts](https://web.dev/app-shortcuts/). But what happens with all the users who have already installed the app with the old icon on their devices? How and when do they get the updated version?

The answer depends on the platform. Let's cover the options available.

您還可以更新應用的元數據，這些元數據主要在 Web 應用清單中設置。例如，更新其圖標、名稱或起始 URL，或者您可以添加應用程序快捷方式等新功能。但是，所有已經在設備上安裝了帶有舊圖標的應用程序的用戶會怎樣呢？他們如何以及何時獲得更新版本？

答案取決於平台。讓我們介紹可用的選項。

<div style="padding:1rem;background-color:#faf6fe;color:#6001ff;">
    



<span style="display:flex">
    
:bulb: 
       <p style="color:#6001ff;margin-top:-1.5em">
       Gotchas陷阱
       </p> 
</span>
    
<p style="color:#6001ff;">
    
The <kbd>id </kbd>  property uniquely identifies your PWA; changing id means your PWA will be considered a completely new PWA. To avoid unexpected behavior, before you set or change the <kbd>id </kbd>   property, read [Uniquely identifying PWAs with the web app manifest id property](https://developer.chrome.com/blog/pwa-manifest-id/).
    
</p>

</div>

<div style="padding:1rem;background-color:#faf6fe;color:#6001ff;margin-top:1rem">
    



<span style="display:flex">
    
:bulb: 
       <p style="color:#6001ff;margin-top:-1.5em">
       Gotchas陷阱
       </p> 
</span>
    
<p style="color:#6001ff;">
    
id 屬性唯一標識你的 PWA；改變 id 意味著你的 PWA 將被認為是一個全新的 PWA。為避免意外行為，在設置或更改 id 屬性之前，請閱讀使用 Web 應用程序清單 id 屬性唯一標識 PWA。
    
</p>

</div>

## Safari on iOS, iPadOS, and Android browsers iOS、iPadOS 和 Android 瀏覽器上的 Safari

On these platforms, the only way to get the new manifest metadata is to re-install the app from the browser.

在這些平台上，獲取新清單元數據的唯一方法是從瀏覽器重新安裝應用程序。


<div style="background-color:#deeafd;padding:1rem;line-height:1.9;margin-top:1rem;color:#174ea6">

If you modify your <kbd>start_url</kbd>  the browser may install the app as a completely new app. However, it has been a common practice to add a manual version identifier within the start_url property, such as /?version=3 to identify the version. From Chrome 96 you can add an id into the manifest to identify your app.
    
</div>

<div style="background-color:#deeafd;padding:1rem;line-height:1.9;margin-top:1rem;color:#174ea6">

如果您修改 start_url，瀏覽器可能會將該應用程序安裝為一個全新的應用程序。但是，通常的做法是在 start_url 屬性中添加手動版本標識符，例如 /?version=3 來標識版本。從 Chrome 96 開始，您可以在清單中添加一個 id 來標識您的應用程序。
    
</div>


## Google Chrome on Android with WebAPK 帶有 WebAPK 的 Android 上的谷歌瀏覽器
When the user has installed your PWA on Android using Google Chrome with [WebAPK](https://web.dev/learn/pwa/installation/#webapks) activated (most of the Chrome PWA installations), the update will be detected and applied based on an algorithm. Check out the details in this [manifest updates](https://web.dev/manifest-updates/) article.

當用戶使用啟用了 WebAPK 的 Google Chrome 在 Android 上安裝了您的 PWA（大多數 Chrome PWA 安裝）時，將根據算法檢測並應用更新。查看此清單更新文章中的詳細信息。

Some additional notes about the process:有關該過程的一些附加說明：

If the user doesn't open your PWA, its WebAPK won't be updated. If the server doesn't respond with the manifest file (there is a 404 error), Chrome won't check for updates for a minimum of 30 days, even if the user opens the PWA.
如果用戶沒有打開你的 PWA，它的 WebAPK 就不會更新。如果服務器沒有響應清單文件（出現 404 錯誤），Chrome 將至少在 30 天內不會檢查更新，即使用戶打開 PWA。


Go to about:webapks in Chrome on Android to see the status of the "needing update" flag, and request an update. In the [Tools and debug](https://web.dev/learn/pwa/tools-and-debug/) chapter, you can read more about this debugging tool.
轉到 about:webapks in Chrome on Android 查看“needing update”標誌的狀態，並請求更新。在工具和調試章節中，您可以閱讀有關此調試工具的更多信息。

## Samsung Internet on Android with WebAPK 帶有 WebAPK 的 Android 上的三星互聯網

The process is similar to the Chrome version. In this case, if the PWA manifest requires an update, during the next 24 hours the WebAPK will be updated on Wi-Fi after [minting the updated WebAPK](https://web.dev/learn/pwa/installation/#webapks).
該過程類似於 Chrome 版本。在這種情況下，如果 PWA 清單需要更新，則在接下來的 24 小時內，WebAPK 將在創建更新後的 WebAPK 後在 Wi-Fi 上更新。


## Google Chrome and Microsoft Edge on desktop 桌面版 Google Chrome 和 Microsoft Edge

On desktop devices, when the PWA is launched, the browser determines the last time it checked the local manifest for changes. If the manifest hasn't been reviewed since the browser last started or hasn't been checked in the last 24 hours, the browser will make a network request for the manifest and then compare it against the local copy.
在桌面設備上，當 PWA 啟動時，瀏覽器會確定上次檢查本地清單是否有更改的時間。如果清單自瀏覽器上次啟動後未被審查或在過去 24 小時內未被檢查，瀏覽器將對清單發出網絡請求，然後將其與本地副本進行比較。

When [selected properties](https://web.dev/manifest-updates/#cr-desktop-trigger) are updated, it will trigger an update after all windows have been closed.
更新選定的屬性時，將在所有窗口關閉後觸發更新。

## Alerting the user 提醒用戶

Some updating strategies need a reload or a new navigation from the clients. You'll want to let the user know there is an update waiting but give them the chance to update the page when it is best for them.

一些更新策略需要從客戶端重新加載或新導航。您需要讓用戶知道有更新正在等待，但要讓他們有機會在最適合他們的時候更新頁面。

To inform the user, there are these options:
要通知用戶，有以下選項：

* Use the DOM or [canvas API](https://developer.mozilla.org/zh-CN/docs/Web/API/Canvas_API) to render a notice on the screen.

* 使用 DOM 或畫布 API 在屏幕上呈現通知。

* Use the [Web Notifications API](https://developer.mozilla.org/zh-CN/docs/Web/API/notification). This API is part of the push permission to generate a notification in the operating system. You will need to request web push permission to use it, even if you don't use the push messaging protocol from your server. This is the only option we have if the PWA is not opened.

* 使用網絡通知 API。此 API 是在操作系統中生成通知的推送權限的一部分。即使您不使用來自服務器的推送消息協議，您也需要請求網絡推送權限才能使用它。如果未打開 PWA，這是我們唯一的選擇。

* Use the [Badging API](https://developer.chrome.com/articles/badging-api/) to show that updates are available in the PWA's installed icon

* 使用 Badging API 在 PWA 的已安裝圖標中顯示更新可用



![](https://i.imgur.com/mIt5Di0.png)


## More about the Badging API  有關徽章 API 的更多信息

The [Badging API](https://developer.chrome.com/articles/badging-api/) lets you mark your PWA's icon with a badge number, or a badge dot on compatible browsers. A badge dot is a tiny mark within the installed icon that expresses something is waiting inside the app.

Badging API 允許您使用徽章編號或兼容瀏覽器上的徽章點來標記 PWA 的圖標。徽章點是已安裝圖標中的一個小標記，表示應用程序內部正在等待某些內容。

![](https://i.imgur.com/Jd6xrLy.png)

You need to call <kbd>setAppBadge(count)  </kbd>  on the 
<kbd> navigator  </kbd> object to set a badge number. You can do this from the window or service worker's context when you know there is an update to alert the user.

您需要在
導航器對象設置徽章編號。當您知道有更新提醒用戶時，您可以從窗口或 Service Worker 的上下文中執行此操作。

```
let unreadCount = 125;
navigator.setAppBadge(unreadCount);
```
To clear the badge, you call <kbd> clearAppBadge() </kbd>  on the same object:

要清除徽章，您可以在同一對像上調用 clearAppBadge() ：

`navigator.clearAppBadge();`


<div style="background-color:#deeafd;padding:1rem;line-height:1.9;margin-top:1rem;color:#174ea6">

The Badging API works on a best-effort mechanism; the browser will do its best to match your request, but sometimes the browser will revert to a different approach. For example, a badge number is not available on some Android devices, so a dot badge is used, no matter the number you specify.
    
</div>

<div style="background-color:#deeafd;padding:1rem;line-height:1.9;margin-top:1rem;color:#174ea6">

Badging API 採用盡力而為機制；瀏覽器會盡力滿足您的請求，但有時瀏覽器會恢復為不同的方法。例如，徽章編號在某些 Android 設備上不可用，因此無論您指定什麼數字，都會使用點徽章。
    
</div>


## Resources 
*  [Service Worker Lifecycle](https://web.dev/service-worker-lifecycle/)
*  [How Chrome handles updates to the web app manifest](https://web.dev/manifest-updates/) 
* [Synchronize and update a PWA in the Background](https://learn.microsoft.com/en-us/microsoft-edge/progressive-web-apps-chromium/how-to/background-syncs)
* [Richer offline experiences with the Periodic Background Sync API](https://developer.chrome.com/articles/periodic-background-sync/)
* [Push API](https://developer.mozilla.org/zh-CN/docs/Web/API/Push_API)
* [Push notifications overview](https://web.dev/push-notifications-overview/)
* [Badging for app icons](https://developer.chrome.com/articles/badging-api/)
* [Workbox 4: Implementing refresh-to-update-version flow using the workbox-window module](https://medium.com/google-developer-experts/workbox-4-implementing-refresh-to-update-version-flow-using-the-workbox-window-module-41284967e79c)