漸進式網頁應用程式:強化 PWA

1. 歡迎

在本實驗室中,您將使用現有的網頁應用程式,並為其新增進階功能。這是漸進式網頁應用程式研討會的一系列配套程式碼研究室中的第六個。先前的程式碼研究室是「提示及評估安裝」。本系列還有兩個程式碼研究室。

課程內容

  • 使用 File System Access API 開啟及儲存使用者檔案系統中的檔案
  • 使用 File Handling API 將已安裝的 PWA 註冊為檔案處理常式
  • 使用 Multi-Screen Window Placement API 開啟視窗時,請選擇正確的螢幕
  • 使用 Screen Wake Lock API 防止螢幕進入睡眠模式

注意事項

  • JavaScript

軟硬體需求

  • 支援上述 API 的瀏覽器。部分 API 可能需要使用已啟用開發人員試用或來源試用的瀏覽器才能完成。

2. 開始設定

首先,請複製或下載完成本程式碼研究室所需的範例程式碼:

如果複製存放區,請確認您位於 pwa05--empowering-your-pwa 分支版本中。ZIP 檔案也包含該分支版本的程式碼。

這個程式碼集需要 Node.js 14 以上版本。取得程式碼後,請在程式碼資料夾中從指令列執行 npm ci,安裝所有需要的依附元件。接著執行 npm start,啟動本程式碼研究室的開發伺服器。

原始碼的 README.md 檔案會說明所有發布的檔案。此外,您在本程式碼研究室中會使用下列主要現有檔案:

金鑰檔案

  • js/lib/actions.js - 提供選單的基礎類別

重要架構注意事項

在本程式碼研究室中,您將編輯 js/lib/action.js,管理應用程式選單中不同按鈕的動作。您可以在已初始化選單的建構函式中存取任何屬性,包括主要文字編輯器的執行個體 this.editor。在本程式碼研究室中,您會用到兩個重要的編輯器方法:

  • this.editor.setContent(content):將編輯器的內容設為提供的內容引數
  • this.editor.content() - 取得編輯器的目前內容

3. 管理檔案

現在,透過 File System Access API,您可以在使用者的電腦上開啟、儲存及建立新檔案。搭配 File Handling API,使用者就能直接在 PWA 中開啟檔案,讓 PWA 完美融入日常生活。

從應用程式內開啟

首先要連結的動作是從應用程式內開啟使用者檔案系統中的檔案。在 js/lib/actions.js 中,於 Actions 類別的 open 方法中編寫程式碼,執行下列操作:

  • 開啟檔案挑選器,挑選副檔名為 .md.markdowntext/markdown 檔案
  • 將頁面標題設為開啟的檔案名稱,並加上 PWA Edit
  • 將檔案處理常式儲存在 this.handler 下方
  • 將編輯器的內容設為檔案的文字內容
  • 將處理常式儲存至 settings-store IndexedDB 資料庫中的 settings 物件儲存空間。

正面:請注意,類別建構函式不能是 async 函式,但您可以在其中呼叫 Promise。

現在您可以開啟檔案,並在載入之間儲存開啟的檔案,但還有兩件事需要完成:在應用程式載入時重新設定處理常式,並在使用者重設應用程式時取消設定。

如要完成第一項作業,請在 js/lib/actions.jsActions 類別的建構函式中執行下列操作:

  • 開啟 settings-store 資料庫
  • settings 物件儲存區取得已儲存的處理常式
  • 如有已儲存的處理常式,請將 this.handler 設為擷取的值,並將網頁標題設為處理常式的檔案名稱 (加上 PWA Edit)

如要重設應用程式的狀態 (可使用 CTRL/CMD+Shift+R 完成),請更新 js/lib/actions.jsActions 類別的 reset 方法,以執行下列操作:

  • 將文件標題設為「PWA Edit
  • 將編輯器的內容設為空白字串
  • this.handler 設為 null
  • settings 物件儲存區刪除已儲存的處理常式

從使用者的檔案系統開啟

現在您已可從應用程式開啟檔案,接下來應允許使用者透過檔案開啟應用程式!將應用程式註冊為裝置的檔案處理常式後,使用者就能從檔案系統的任何位置開啟應用程式中的檔案。

負面:您可能需要啟用開發人員或來源試用,這項功能才能運作。如需啟用開發人員試用版,建議您在 Chrome Canary 的副本中啟用,而不是在一般瀏覽器中啟用。如要啟用原始碼試用,請照常註冊,然後將 標記新增至 index.html

首先,請在 manifest.json 中新增 file_handlers 項目,執行下列操作:

  • 開始營業時間:/
  • 接受 text/markdown,副檔名為 .md.markdown

這樣一來,使用者就能透過您的應用程式開啟檔案,但實際上不會在應用程式中開啟檔案。如要這麼做,請在 js/lib/actions.jsActions 類別中執行下列操作:

  • 在建構函式中新增 window.launchQueue 消費者,並使用處理常式呼叫 this.open (如有)。
  • 更新 this.open,接受選用的啟動處理常式
    • 如果存在且是 FileSystemFileHandle 的例項,請將其做為函式的檔案處理常式
    • 如果沒有,請開啟檔案挑選器

完成上述兩項操作後,請安裝 PWA,然後嘗試從檔案系統開啟檔案!

儲存檔案

使用者可以選擇兩種不同的儲存路徑:將變更儲存到已開啟的檔案,或是儲存到新檔案。使用 File System Access API 儲存至新檔案時,實際上是建立新檔案並取得檔案控制代碼,因此首先要從現有控制代碼儲存。

js/lib/actions.jsActions 類別中,於 save 方法執行下列操作:

  • this.handler 取得處理常式,如果不存在,則從資料庫取得已儲存的處理常式
  • 建立檔案處理常式的 FileSystemWritableFileStream
  • 將編輯器的內容寫入串流
  • 關閉串流

能夠儲存檔案後,就可以實作另存新檔功能。如要這麼做,請在 js/lib/actions.jsActions 類別中,於 saveAs 方法執行下列操作:

  • 顯示儲存檔案選擇器,將其描述為 Markdown File,並接受副檔名為 .mdtext/markdown 檔案
  • this.handler 設為傳回的處理常式
  • 將處理常式儲存至 settings 物件存放區
  • 等待 this.save 完成,將內容儲存到新建立的檔案

完成後,請返回 save 方法,檢查 handler 是否存在,如果不存在,請等待 this.saveAs 完成,再嘗試寫入。

4. 顯示預覽畫面

使用者希望在 Markdown 編輯器中預覽算繪輸出內容。使用 Window Management API,在使用者主要螢幕上開啟已算繪內容的預覽畫面。

開始前,請建立 js/preview.js 檔案,並在其中加入下列程式碼,以便在載入時顯示預覽畫面:

import { openDB } from 'idb';
import { marked } from 'marked';

window.addEventListener('DOMContentLoaded', async () => {
  const preview = document.querySelector('.preview');
  const db = await openDB('settings-store');
  const content = (await db.get('settings', 'content')) || '';

  preview.innerHTML = marked(content);
});

預覽畫面應有下列行為:

  • 使用者點選預覽按鈕時,如果預覽畫面未開啟,系統應開啟預覽畫面
  • 使用者點選預覽按鈕時,如果預覽畫面已開啟,則應關閉預覽畫面
  • 使用者關閉或重新整理 PWA 時,預覽畫面應會關閉

依序執行這些步驟,首先編輯 js/lib/actions.jsActions 類別的 preview 方法,完成下列操作:

  • 使用 Window Management API 取得可用螢幕
  • 篩選畫面,找出主要畫面
  • 開啟 /preview 的視窗,標題為 Markdown preview,占據主要螢幕可用寬度的一半和整個可用高度,位置則占據該螢幕右半邊的可用空間。可用尺寸不包括螢幕保留區域,例如系統功能表列、工具列、狀態或位置。
  • 將這個開啟的視窗儲存到「this.previewWindow
  • 在方法頂端,檢查是否存在 this.previewWindow,如果存在,請關閉視窗並取消設定 this.previewWindow,而不是開啟視窗預覽畫面

最後,在 js/lib/actions.js 中,於 Actions 類別的建構函式結尾執行下列操作:

  • beforeunload 活動期間關閉 this.previewWindow

5. 專注模式

最後,我們希望為使用者提供不受干擾的寫作模式。無干擾模式不僅能避免其他應用程式造成畫面雜亂,還能防止使用者螢幕進入休眠狀態。如要這麼做,請使用 Screen Wake Lock API

喚醒鎖定按鈕的運作方式與預覽按鈕相同,可切換開啟和關閉狀態。如要這麼做,請在 js/lib/actions.jsActions 類別的 focus 方法中,執行下列操作:

  • 檢查文件是否含有全螢幕元素
  • 如果可以:
    • 結束全螢幕
    • 如果 this.wakeLock 存在,請釋放 Wake Lock 並重設 this.wakeLock
  • 如果沒有,請按照下列步驟操作:
    • 要求喚醒鎖定信號,並設為 this.wakeLock
    • 要求文件主體進入全螢幕模式。

6. 恭喜!

您已瞭解如何管理系統檔案、使用 File System Access API 和 File Handling API 將 PWA 與系統整合、使用 Window Management API 在不同螢幕開啟視窗,以及使用 Screen Wake Lock API 防止螢幕進入休眠狀態。

本系列下一個程式碼研究室是「Service Worker Includes」。