發布日期:2020 年 12 月 2 日
自從推出Trusted Web Activity 後,Chrome 團隊已簡化 Bubblewrap 的使用方式。我們新增了其他功能 (例如 Google Play 帳款服務整合),並讓這項服務能夠在更多平台上運作,例如 ChromeOS。
Bubblewrap 和 Trusted Web Activity 功能
Bubblewrap 可協助您建立應用程式,在信任的網頁活動中啟動 PWA,無須瞭解特定平台的工具。
簡化設定流程
先前,使用 Bubblewrap 需要手動設定 Java Development Kit 和 Android SDK,這兩者都容易發生錯誤。這項工具現在會在首次執行時自動下載外部依附元件。
您仍可選擇使用現有的依附元件安裝作業 (如果您偏好這樣做),而新的 doctor
指令可協助找出問題,並建議修正設定,現在您可以透過指令列使用 updateConfig
指令更新設定。
改善精靈
使用 init
建立專案時,Bubblewrap 需要產生 Android 應用程式所需的資訊。這項工具會從 Web App 資訊清單擷取值,並在可行時提供預設值。
您可以在建立新專案時變更這些值,但先前各欄位的含義並不明確。我們重新建構了初始化對話方塊,為每個輸入欄位提供更完善的說明和驗證機制。
顯示全螢幕和方向支援
在某些情況下,您可能希望應用程式盡可能使用螢幕的所有空間,在建構 PWA 時,您可以將 display
欄位從網頁應用程式資訊清單設為 fullscreen
,實現這項功能。
當 Bubblewrap 在 Web 應用程式資訊清單中偵測到全螢幕選項時,就會將 Android 應用程式設為以全螢幕模式 (或以 Android 專屬術語來說,就是「沉浸式模式」) 啟動。
網頁應用程式資訊清單中的 orientation
欄位會定義應用程式應以直向模式、橫向模式,還是裝置目前使用的方向啟動。Bubblewrap 會讀取網頁應用程式資訊清單欄位,並在建立 Android 應用程式時將其用作預設值。
您可以自訂這兩種設定,並納入 bubblewrap init
流程中。
AppBundles 輸出內容
應用程式套件是一種應用程式的發布格式,可以委派最終產生的 APK 產生並簽署給 Google Play。這種做法可讓您在使用者從商店下載應用程式時,提供較小的檔案。
Bubblewrap 會將應用程式封裝為應用程式軟體包,並儲存在名為 app-release-bundle.aab
的檔案中。您應在將應用程式發布至 Play 商店時使用此格式,因為 商店自 2021 年起就要求使用此格式。
地理位置委派
無論技術為何,使用者都希望在裝置上安裝的應用程式能夠一致運作。在受信任的網路活動中使用時,GeoLocation 權限現在可以委派給作業系統。啟用後,使用者就會看到與使用 Kotlin 或 Java 建構的應用程式相同的對話方塊,並且找到了在同一個位置管理權限的控制項。
這項功能可透過 Bubblewrap 新增,但由於它會為 Android 專案新增額外依附元件,因此您應僅在網頁應用程式使用地理位置權限時啟用這項功能。
最佳化二進位檔
儲存空間有限的裝置常常用於全球,而這些裝置的擁有者往往偏好小型的應用程式。使用信任的網路活動的應用程式會產生小型二進位檔,可消除使用者的部分疑慮。
Bubblewrap 已經過最佳化,減少所需 Android 程式庫的清單,產生的二進位檔因此縮小了 800k。實際上,低於先前版本產生平均大小的一半。如要利用較小的二進位檔,只需使用最新版本的 Bubblewrap 更新應用程式即可。
如何更新現有應用程式
Bubblewrap 產生的應用程式由網頁應用程式和可開啟 PWA 的輕量 Android 包裝函式組成。即使在受信任的網路活動中開啟 PWA,其與任何網頁應用程式的更新週期相同,原生包裝函式仍可以更新 (且需要更新)。
您應更新應用程式,確保應用程式使用的是最新版的包裝函式,並推出最新的錯誤修正和功能。安裝最新版的 Bubblewrap 後,update
指令會將最新版的包裝函式套用至現有專案:
npm update -g @bubblewrap/cli
bubblewrap update
bubblewrap build
更新這些應用程式的另一個原因,是為了確保 Web 資訊清單的變更內容會套用至應用程式。請使用新的 merge
指令:
bubblewrap merge
bubblewrap update
bubblewrap build
品質標準更新
Chrome 86 對受信任網路活動品質標準做出了變更,詳情請參閱「透過受信任網路活動整合 PWA 時的品質標準有所變更」一文。
簡單來說,您必須確保應用程式能夠處理下列情況,以免發生當機情形:
- 無法在應用程式啟動時驗證數位資產連結
- 無法針對離線網路資源要求傳回 HTTP 200
- 在應用程式中傳回 HTTP 404 或 5xx 錯誤。
除了確保應用程式通過Digital Asset Links 驗證之外,服務工作者還可以處理下列其他情況:
self.addEventListener('fetch', event => {
event.respondWith((async () => {
try {
return await fetchAndHandleError(event.request);
} catch {
// Failed to load from the network. User is offline or the response
// has a status code that triggers the Quality Criteria.
// Try loading from cache.
const cachedResponse = await caches.match(event.request);
if (cachedResponse) {
return cachedResponse;
}
// Response was not found on the cache. Send the error / offline
// page. OFFLINE_PAGE should be pre-cached when the service worker
// is activated.
return await caches.match(OFFLINE_PAGE);
}
})());
});
async function fetchAndHandleError(request) {
const cache = await caches.open(RUNTIME_CACHE);
const response = await fetch(request);
// Throw an error if the response returns one of the status
// that trigger the Quality Criteria.
if (response.status === 404 ||
response.status >= 500 && response.status < 600) {
throw new Error(`Server responded with status: ${response.status}`);
}
// Cache the response if the request is successful.
cache.put(request, response.clone());
return response;
}
Workbox 會採用最佳做法,並在使用服務工作者時移除常用程式碼。或者,您也可以考慮使用 Workbox 外掛程式來處理這些情況:
export class FallbackOnErrorPlugin {
constructor(offlineFallbackUrl, notFoundFallbackUrl, serverErrorFallbackUrl) {
this.notFoundFallbackUrl = notFoundFallbackUrl;
this.offlineFallbackUrl = offlineFallbackUrl;
this.serverErrorFallbackUrl = serverErrorFallbackUrl;
}
checkTrustedWebActivityCrash(response) {
if (response.status === 404 || response.status >= 500 && response.status <= 600) {
const type = response.status === 404 ? 'E_NOT_FOUND' : 'E_SERVER_ERROR';
const error = new Error(`Invalid response status (${response.status})`);
error.type = type;
throw error;
}
}
// This is called whenever there's a network response,
// but we want special behavior for 404 and 5**.
fetchDidSucceed({response}) {
// Cause a crash if this is a Trusted Web Activity crash.
this.checkTrustedWebActivityCrash(response);
// If it's a good response, it can be used as-is.
return response;
}
// This callback is new in Workbox v6, and is triggered whenever
// an error (including a NetworkError) is thrown when a handler runs.
handlerDidError(details) {
let fallbackURL;
switch (details.error.details.error.type) {
case 'E_NOT_FOUND': fallbackURL = this.notFoundFallbackUrl; break;
case 'E_SERVER_ERROR': fallbackURL = this.serverErrorFallbackUrl; break;
default: fallbackURL = this.offlineFallbackUrl;
}
return caches.match(fallbackURL, {
// Use ignoreSearch as a shortcut to work with precached URLs
// that have _WB_REVISION parameters.
ignoreSearch: true,
});
}
}