Progress Web Apps(PWAs) 讓開發人員沿用 Web 技術做到接近 native app-like experience,省去需要開發不同平臺的成本。但 PWA 最大難度就是漸進式把 Web site 功能效果做到接近 native apps 的品質。
根據 Progress Web Apps on Windows 的介紹,要做到好的 PWA apps,需要滿足下圖特點:
支援 offline 跟 push notification 是 PWAs 最基本的需求,進一步則是可從 web search 找到内容並開啓 App 或是分享連結來操作。
有 PWA Builder 幫忙,讓現有的網站容易變成 App 上架到 Store。
往下介紹參考 Generate your Progressive Web App 如何建立 PWA App,並補充需注意的地方:
- 輸入特定 URL 之後,PWABuilder 會解譯出網站的説明,並顯示需要調整的地方,最常見的問題就是:missing image:
雖然不影響封裝,但建議所有圖片都提供省去後面封裝檔案缺圖的問題; - 在建立 Manifest 時可以搭配 Web App Manifest 來寫入必要的資訊,其中比較重要的:定義好的 manifest.json 可以加入到網站的宣告: <meta src="manifest.json" />,方便 PWABuilder 下載,而 Browser 也會參考 manifest.json 的定義安裝 web application。如果安裝成功,在設備的 home screen 就會看到該 web application。
- name 或 short_name:代表 Web Application 的名稱。
- scope:代表可以瀏覽的範圍,如果沒有填寫會以 start_url 的目錄爲主。例如: start_url 是 /page/welcome.html 那 scope 可以存取 /page/ 以下的内容;詳細可參考 4. Navigation scope 。
- display:代表如何呈現在系統上,具有:fullsreen, standalone, minimal-ui, browser。
- start_url:預設為用戶啓動 web application 要顯示的 URL。
- icons:圖片的集合,與 PWA 要被安裝在那個平臺有關係,可以利用 App Image Generator 建立各平臺的圖示。
- serviceworker:定義 service worker 的詳細資訊,例如:
"serviceworker": { "src": "sw.js", "scope": "/foo", "update_via_cache": "none" }
- Service Workers
它是讓 browser 可在背景運作的 scripts,在 browser 中利用程式管理 web/HTTP request 作爲 network proxy。
利用下面的範例程式把 service workers 注冊到您的網站:
[注意]if (navigator.serviceWorker.controller) { console.log('[PWA Builder] active service worker found, no need to register') } else { //Register the ServiceWorker navigator.serviceWorker.register('pwabuider-sw.js', { scope: './' }).then(function(reg) { console.log('Service worker has been registered for scope:'+ reg.scope); }); }
- 可利用 is ServiceWorker ready 或是 if('serviceWorker' in navigator) 來檢查瀏覽器是否支援
- 只支援 HTTPS 或 localhost
從上圖可理解注冊 Service Worker 之後,完成 install 後會進入 active 並在背景運作,如果過程失敗它將不會被啓動,但再下一次進去這個網站時會執行一次。
如上面範例,在 install 完畢之後則加入一個 offline.html 到 cache 裏面。//This is the "Offline page" service worker //Install stage sets up the offline page in the cache and opens a new cache self.addEventListener('install', function(event) { var offlinePage = new Request('offline.html'); event.waitUntil( fetch(offlinePage).then(function(response) { return caches.open('pwabuilder-offline').then(function(cache) { console.log('[PWA Builder] Cached offline page during Install'+ response.url); return cache.put(offlinePage, response); }); })); }); //If any fetch fails, it will show the offline page. //Maybe this should be limited to HTML documents? self.addEventListener('fetch', function(event) { event.respondWith( fetch(event.request).catch(function(error) { console.error( '[PWA Builder] Network request Failed. Serving offline page ' + error ); return caches.open('pwabuilder-offline').then(function(cache) { return cache.match('offline.html'); }); } )); }); //This is a event that can be fired from your page to tell the SW to update the offline page self.addEventListener('refreshOffline', function(response) { return caches.open('pwabuilder-offline').then(function(cache) { console.log('[PWA Builder] Offline page updated from refreshOffline event: '+ response.url); return cache.put(offlinePage, response); }); });
在 active 狀態時,Service Worker 將控制 scope 下 pages 的交易,因此,當有 http request 出現時會觸發 fetch 事件,可以搭配 event.responseWith() 先檢查是否有 caches ,如果有就可以直接回復,如果沒有才真的轉給 server。如下範例:
如果使用 PWABuilder 它會根據您選擇的 Service Worker 需要的功能 (例如: offline page, offline copy of pages, offline copy with backup offline pages, cache-first network 或 advanced pre-cache)產生必要的 js 檔案,記得把它放到您的網站。self.addEventListener('fetch', function(event) { event.respondWith( caches.match(event.request) .then(function(response) { // Cache hit - return response if (response) { return response; } return fetch(event.request); } ) ); });
更多 Service Worker 的介紹可以參考 Service Worker。
利用 PWABuilder Web tool 產生 manifest.xml 與選擇 Service Worker 支援的功能後,選擇建立 packages 或是把專案下載下來,如下圖:
如果您選擇 appx 的下載可以從 zip 中找到 windows.appx,如果不是則需要自己編譯,下面來看有那些步驟。
zip 解開的目錄為:
{app name}-windows10
->\projects
->\PWA
->\Store packages
->\windows10
->\manifest (封裝成 appx 必要的 appxmanifest.xml 與相關圖片)
->\package (封裝成品的目錄)
->\source (專案的 source code, 裏面有 package.appxmanifest 與相關圖片)
->\generationInfo.json
->\manifest.json (這個可以放在網站的宣告)
->\test-install.ps1 (檢查執行安裝前的邏輯)
->\Windows10-next-steps.md
->\serviceWorker1
- 利用 Visual Studio 2017 開啓 source 目錄下的 App.jsproj,並綁定 Dev Center 中的 Project 來拿到 StoreKey.pfx 與相關的參數
- 把 manifest 目錄下的 appxmanifest.xml 中被標記為 INSERT-YOUR-PACKAGE-IDENTITY-NAME-HERE 的值改爲正確的值,包括:PublisherDisplayName,Identity 中的 Name, Publisher, Version
- 如果您想要更新 App 的 icons,可以利用 App Image Generator 選建立 Windows 10 的圖示,並把它們放到 manifest 與 source 目錄中的 images 目錄裏,並把 resources.pri 讓封裝的時候可以重新建立資源檔
- 安裝 node.js runtime 與 npm install pwabuilder -g,可以參考 Quick Start PWA using CLI tools
- 利用 PWA CLI tools 下指令來封裝 app:
pwabuilder package {app name}-windows10\projects -p windows10 -l debug
產生的 windows.appx 會放在 package 目錄,這裏不加 -a 的參數到指令裏面,因爲還不需要自動上傳到 Store - 把 StoreKey.pfx 加入 windows.appx 的憑證,加入憑證之後就可以安裝到 Windows 10 設備:
cd "C:\Program Files (x86)\Windows Kits\10\bin\x86\" SignTool sign /fd SHA256 /a /f "C:\{app name}-windows10\projects\PWA\Store packages\windows10\package\StoreKey.pfx" "C:\{app name}-windows10\projects\PWA\Store packages\windows10\package\windows.appx"
下面多補充説明如果把 PWABuilder 建立好的 appx 安裝在 XBOX 上面,網站需要加入那些調整。
把 PWA App 放在 Xbox 上執行
UWP - 開發 Xbox App 處理 TV-safe 與 UWP - 開發 Xbox App 處理 XY navigation 介紹過在 Xbox 上開發 App 要處理:- 如何停用滑鼠模式:
- 下載 directionalnavigation-1.0.0.0.js 加到網頁裏面: <script src="directionalnavigation-1.0.0.0.js"></script>
- 在 javascript 中加入 navigator.gamepadInputEmulation = "gamepad";。
gamepadInputEmulation 有 3 種模式:預設是 mouse (啓用滑鼠模式);keyboard (停用滑鼠模式,切換用 keyboard 輸入的 DOM 鍵盤事件);gamepad (關閉滑鼠模式,不會產生 DOM 鍵盤事件,改使用 DOM 或 WinRT gamepad APIs)
- 如何關閉縮放比例:XAML App 預設調整為 200%, HTML App 則爲 150%。可以關閉並改用裝置的實際像素尺寸 (1910 x 1080 像素)。
JavaScript 的指令:
或是 CSS:var result = Windows.UI.ViewManagement.ApplicationViewScaling.trySetDisableLayoutScaling(true);
@media (max-height: 1080px) { @-ms-viewport { height: 1080px; } }
- 如何在螢幕邊緣繪製 UI:預設 App 會針對電視保留安全區域(TV-safe area),確保内容能夠正常顯示。建議可以關閉,JavaScript 的指令:
Windows.UI.ViewManagement.ApplicationView.getForCurrentView().setDesiredBoundsMode(Windows.UI.ViewManagement.ApplicationViewBoundsMode.useCoreWindow);
- Javascript 處理 XY navigation 可以參考 Using DirectionalNavigation
Progress Web Apps(PWAs) 確實方便,但並不是全部 App 都能這樣取代,需要看 App 本身需求與硬體相依程度,不過大部分 80% 都能使用。尤其是 Service Worker 的邏輯需要特別注意。
另外需要注意開發時,如果需要操作各個平臺的 APIs 只能經由 JavaScript 來互動,我建議可以多補充這方便的内容,有助於判斷那些功能可否實現。希望對大家有所幫助,謝謝。
References:
- Microsoft Edge developer documentation
- 服務工作線程:簡介
- Service Worker API
- 7 REASONS WHY PROGRESSIVE WEB APPS ARE THE FUTURE OF WEB DEVELOPMENT
- Using DirectionalNavigation
- TV-safe area
- 如何停用滑鼠模式
- 如何關閉縮放比例
- 如何在螢幕邊緣繪製 UI
- 使用 Visual studio 封裝 UWP app
- App packager (MakeAppx.exe)
- 使用 SignTool 簽署應用程式套件
- Progress Web Apps(PWAs)
- 使用 JavaScript 建立 UWP 遊戲
- 使用 three.js 建立 3D JavaScript 遊戲
- Service Worker
- Browser push notifications using JavaScript
- Introduction to Push Notifications
沒有留言:
張貼留言