讓網頁應用程式保持簡單明瞭並不容易。在本單元中,您將瞭解網路 API 如何與執行緒搭配運作,以及如何將這類 API 用於狀態管理等常見的 PWA 模式。
簡單易用
「一個角色、一項工作、一個概念或一個維度。」
但要強調一點簡單,並非關於:
「有一個執行個體或執行一項作業。」
不管有沒有簡單的東西,那就是其相互連結的方式。
複雜來說必須具有繫結、編織或運用 Rich 的術語來完成工作。只要計算某個項目管理的角色、工作、概念或維度數量,就可以計算其複雜性。
簡單易用是軟體開發流程中不可或缺的一環,因為簡單的程式碼更容易理解與維護。此外,簡單好用的網頁應用程式也必須化繁為簡,因為這樣可讓使用者在各種可能的情況下,快速地使用我們的應用程式。
管理 PWA 的複雜度
我們為網頁編寫的所有 JavaScript 會集中輕觸主執行緒。不過,主要執行緒本身存在許多複雜性,因此身為開發人員,您無法控制這類工作。
主要執行緒如下:
- 負責繪圖頁面本身是複雜的多步驟程序,包含計算樣式、更新圖層及合成圖層,以及在螢幕上繪圖。
- 負責監聽事件並做出回應,包括捲動等事件。
- 負責載入及卸載頁面。
- 管理媒體、安全性和身分識別。 這就是您編寫的任何程式碼之前,甚至可以在該執行緒上執行,例如:
- 處理 DOM。
- 存取敏感 API,例如裝置功能或媒體/安全性/身分識別。
因此,Surma 在 2019 年 Chrome 開發人員高峰會的演講中提到,主要執行緒出現過度工作,收益過低。
但大多數應用程式程式碼也存在於主執行緒上。
上述所有程式碼都會增加主執行緒的複雜度。瀏覽器只能使用主執行緒在螢幕上安排及轉譯內容。因此,當程式碼需要更多的處理能力才能完成程式碼時,我們就必須快速執行程式碼,因為執行應用程式邏輯所需的每秒鐘操作一次,就是瀏覽器無法回應使用者輸入內容或重新繪製網頁的第二位。
如果互動無法輸入內容、影格遺失或使用網站的時間太長,使用者就會感到不悅、覺得應用程式故障,導致信心下滑。
壞消息了嗎?增加主執行緒的複雜性,幾乎可以確保難以達成這些目標的方法。好消息是,由於主要執行緒需要執行的工作十分明確,因此可用於做為指引,減少對應用程式其餘部分的依賴。
關注點分離
網頁應用程式有很多用途的工作,但大致上來說,其實您可以將其細分為直接觸及 UI 的工作,以及無法直接處理 UI 的工作。UI 的運作方式如下:
- 直接輕觸 DOM。
- 使用可觸控裝置功能的 API,例如通知或檔案系統存取權。
- 觸控身分,例如使用者 Cookie、本機或工作階段儲存空間。
- 管理媒體,例如圖片、音訊或影片。
- 可能造成安全性方面的影響,必須由使用者手動核准,例如網路序列 API。
非 UI 工作可能包括:
- 純計算。
- 資料存取 (擷取、索引資料庫等)。
- 加密編譯。
- 訊息。
- 建立或操控 Blob 或串流。
非 UI 工作通常是由 UI 工作所預訂:使用者按一下會觸發 API 的網路要求,而該按鈕會傳回剖析結果,然後據此更新 DOM。編寫程式碼時,我們通常會考慮這種端對端體驗,但該流程的各個部分通常不在此限。UI 工作和非 UI 工作之間的界線,必須視為端對端體驗,因為這是降低主執行緒複雜度的第一個位置。
專心處理單一工作
簡化程式碼最直觀的方法之一就是分解函式,因此每一種都專注於單一工作。任務可以根據端對端體驗找出的界線來決定:
- 首先,回應使用者輸入的內容。這就是 UI 的運作方式。
- 接下來,提出 API 要求。這並非 UI 運作。
- 接下來,請剖析 API 要求。這同樣是非 UI 的運作方法。
- 接下來,決定 DOM 的變更。這可能是 UI 可以運作的,或者您使用的是虛擬 DOM 實作等服務,可能無法使用 UI。
- 最後,變更 DOM這就是 UI 的運作方式。
第一個明確的界線是 UI 工作和非 UI 工作之間的明確界線。接著需要做出判斷呼叫:製作並剖析 API 要求一項工作 (一或兩個)?如果 DOM 變更並非 UI 有效,它們是否隨附於 API 中?在同一個討論串中嗎?位於其他執行緒中嗎?如要簡化程式碼集並順利將某些部分從主執行緒移出,關鍵在於此處的適當分隔層級。
可組合函式
如要將大型端對端工作流程分成較小的部分,您必須考量程式碼集的可組合性。請從功能性程式設計中汲取提示,並思考以下幾點:
- 將應用程式工作類型分類。
- 為這些憑證建構常用的輸入和輸出介面。
舉例來說,所有 API 擷取工作都會擷取 API 端點,並傳回標準物件陣列,然後所有資料處理函式都會採用並傳回標準物件的陣列。
JavaScript 提供結構化副本演算法,可用於複製複雜的 JavaScript 物件。網路工作程式在傳送訊息時會使用這個字串,而 IndexedDB 會使用該字型儲存物件。選擇可與結構化複製演算法搭配使用的介面,讓介面執行起來更有彈性。
瞭解這點後,您可以將程式碼分類,並建立這些類別的通用 I/O 介面,藉此建立可組合函式的程式庫。可組合程式碼是簡易程式碼集的一個特徵:鬆耦合的可互換部分彼此相鄰,彼此相互建構,而不是有深度互連且無法輕易分隔的複雜程式碼。在網站上,可組合項程式碼可能意味著過度處理主執行緒之間的差異。
準備好程式碼後,就可以從主執行緒中取得一些程式碼了。
使用網路工作站降低複雜性
Web Worker 是一種經常使用率偏低但廣泛使用的網路功能,可讓您拋出主執行緒上的工作。
Web worker 可讓 PWA 在主執行緒外執行 (部分) JavaScript。
工作站分為三種。
專用工作站是描述網路 worker 時最常想到的,但可以在 PWA 的單一執行個體中,使用單一指令碼使用。請盡可能將未直接與 DOM 互動的工作移至網路工作站,以改善效能。
共用工作站與專屬 worker 類似,差別只在於多個指令碼可以跨多個開啟視窗共用工作站。這可提供專屬 worker 的好處,但視窗和指令碼之間具有共用狀態和內部結構定義。
舉例來說,共用工作站可以管理 PWA IndexedDB 的存取權和交易,並透過所有呼叫指令碼播送交易結果,進而回應變更。
本課程將介紹最終網路工作站:Service Worker。這項服務會當做網路要求的 Proxy,並在 PWA 的所有執行個體之間共用。
親自試試
現在來完成程式碼了!根據您在本單元學到的內容,從頭開始建構 PWA。