使用 Angular 6 構建 PWA
已發表: 2022-03-10 在本教程中,我們將使用最新的 Angular 6 通過實現構成 PWA 的核心原則來構建 PWA。 我們將首先創建一個使用 JSON API 的前端 Web 應用程序。 為此,我們將使用 Angular HttpClient
模塊將 HTTP 請求發送到從 Simplified JavaScript Jargon GitHub 存儲庫生成的靜態 JSON API。 我們還將使用 Material Design 通過 Angular Material 包構建 UI。
接下來,我們將使用 Chrome DevTools 的“審核”面板(Lighthouse)來根據 PWA 的核心原則分析我們的 Web 應用程序。 最後,我們將根據 Lighthouse 報告中的“Progressive Web App”部分解釋 PWA 功能並將其添加到我們的 Web 應用程序中。
在開始實施 PWA 之前,讓我們先介紹一下 PWA 和 Lighthouse。
推薦閱讀: Native 和 PWA:選擇,而不是挑戰者!
什麼是 PWA?
漸進式 Web 應用程序或 PWA 是一種 Web 應用程序,它具有一組功能(類似於原生應用程序),可為用戶提供類似應用程序的體驗。 PWA 需要滿足我們接下來會看到的一組基本要求。 PWA 類似於原生應用,但通過 URL 從 Web 服務器部署和訪問,因此我們不需要通過應用商店。
PWA 需要:
- 進步
為每個用戶工作,無論選擇何種瀏覽器,因為它們是以漸進增強為核心原則構建的。 - 響應式
適合任何外形尺寸、台式機、移動設備、平板電腦或其他任何設備。 - 獨立於連接
增強服務人員以離線或在低質量網絡上工作。 - 類應用
使用 app-shell 模型提供應用風格的導航和交互。 - 新鮮的
由於服務工作者更新過程,始終保持最新狀態。 - 安全的
通過 HTTPS 提供服務,以防止窺探並確保內容未被篡改。 - 可發現的
由於 W3C 清單和服務工作者註冊範圍允許搜索引擎找到它們,因此可以識別為“應用程序”。 - 可重新接合
通過推送通知等功能輕鬆重新參與。 - 可安裝
允許用戶將他們認為最有用的應用程序“保留”在主屏幕上,而無需使用應用程序商店。 - 可鏈接
通過 URL 輕鬆共享,無需複雜的安裝。
介紹燈塔
Lighthouse 是由 Google 創建的開源審計工具,可用於審計網站和應用程序的可訪問性性能、SEO、最佳實踐和 PWA 功能。
您可以從 Chrome DevTools 中的Audit選項卡作為 Node.js 中的模塊或 CLI 工具訪問 Lighthouse。 您可以通過提供 URL 然後運行審核來使用 Lighthouse,這將為您提供包含審核結果的報告,這些結果基本上是關於如何改進 Web 應用程序的建議。
安裝 Angular CLI v6 並生成項目
在本節中,我們將安裝最新版本的 Angular CLI,然後我們將使用它來創建一個新的 Angular 6 項目。
Angular CLI 需要Node.js >= 8.9+ ,所以首先通過運行以下命令確保您安裝了所需的版本:
$ node -v
如果您沒有安裝 Node.js,您可以直接前往官方 Node 下載頁面並獲取您系統的 Node 二進製文件。
現在,您可以通過運行以下命令繼續安裝最新版本的 Angular CLI:
$ npm install -g @angular/cli
注意:根據你的 npm 配置,你可能需要添加_sudo_
來全局安裝包。
您可以通過在終端中運行以下命令來生成 Angular 6 項目:
$ ng new pwademo
這將創建一個結構如下的項目:
完成的大部分工作都在包含應用程序源代碼的src/
文件夾中。
創建 Angular 應用程序
生成項目後,我們將構建一個使用 JSON API 並在主頁上顯示項目的 Web 應用程序。 我們將使用HttpClient服務來發送 HTTP 請求,並使用 Angular Material 來構建 UI。
添加角度材質
感謝 Angular CLI v6 和新的ng add命令,只需一個命令即可將 Angular Material 添加到您的項目中。 您只需要從終端運行以下命令:
$ cd pwademo $ ng add @angular/material
您可以從屏幕截圖中看到該命令從 npm 安裝所需的包並更新一堆文件以在您的項目中設置以前需要手動更新的 Angular Material。
設置HttpClient
並使用 JSON API
現在,讓我們設置 Angular 項目以使用HttpClient
發送 HTTP 請求。 首先,您需要在src/app/app.module.ts
文件中的主應用程序模塊中導入HttpClientModule
模塊:
/*...*/ import { HttpClientModule } from '@angular/common/http'; @NgModule({ declarations: [ AppComponent ], imports: [ /*...*/ HttpClientModule ], providers: [], bootstrap: [AppComponent] }) export class AppModule { }
而已。 我們現在可以在屬於主模塊的任何組件或服務中註入和使用HttpClient
。
出於演示目的,我們將使用從Simplified JavaScript Jargon GitHub 存儲庫中靜態生成的 JSON API。 如果您正在使用任何其他資源,請確保您啟用了 CORS,以便瀏覽器不會因為Same Origin Policy而不允許讀取遠程資源。
讓我們創建一個與 API 交互的服務。 在您的項目文件夾中,運行:
$ ng g service api
這將在src/app/api.service.ts
文件中創建一個名為ApiService
的服務。
現在打開src/app/api.service.ts
文件並更新它以反映以下更改:
import { Injectable } from '@angular/core'; import { HttpClient } from '@angular/common/http'; import { Observable } from 'rxjs'; export interface Item{ name: string; description: string; url: string; html: string; markdown: string; } @Injectable({ providedIn: 'root' }) export class ApiService { private dataURL: string = "https://www.techiediaries.com/api/data.json"; constructor(private httpClient: HttpClient) {} fetch(): Observable<Item[]>{ return <Observable<Item[]>this.httpClient.get(this.dataURL); } }
我們首先導入了HttpClient
和Observable
類,然後將HttpClient
作為httpClient
注入到構造函數中,並添加了一個fetch()
方法,該方法調用HttpClient
的get()
方法(用於向我們的 JSON 端點發送 HTTP GET 請求)並返回一個 Observable我們可以稍後訂閱。
我們還聲明了一個Item
接口,它表示返回的 JSON 數據的單個項目。
接下來從應用程序組件中導入此服務。 打開src/app/app.component.ts
文件並添加:
import { Component, OnInit } from '@angular/core'; import { ApiService } from './api.service'; import { Item } from './api.service'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent implements OnInit{ title = 'pwademo'; items: Array<Item>; constructor(private apiService: ApiService){ } ngOnInit(){ this.fetchData(); } fetchData(){ this.apiService.fetch().subscribe((data: Array<Item>)=>{ console.log(data); this.items = data; }, (err)=>{ console.log(err); }); } }
我們導入之前創建的ApiService
其註入為apiService
,我們還導入了表示 JSON 數據的單個項目的Item
類,我們聲明了Array<Item>
類型的items
變量,它將保存獲取的項目。
接下來,我們添加一個fetchData()
方法,該方法調用我們在ApiService
中定義的fetch()
方法,該方法返回一個 Observable。 我們只需訂閱這個 observable 以便向我們的 JSON 端點發送一個 GET 請求並獲取我們最終分配給items
數組的響應數據。
我們在ngOnInit()
生命週期事件中調用fetchData()
方法,因此一旦AppComponent
組件初始化就會調用它。
添加應用程序 UI
我們的應用程序 UI 將包含一個導航欄和將使用 Angular Material 創建的頁面框架。
在使用 Angular Material 組件之前,您需要導入它的模塊。 每個 Material 組件都屬於它自己的模塊。
打開src/app/app.module.ts
文件並添加以下導入:
/*...*/ import { MatToolbarModule } from '@angular/material/toolbar'; import { MatCardModule } from '@angular/material/card'; import { MatButtonModule } from '@angular/material/button'; @NgModule({ declarations: [ AppComponent ], imports: [ /*...*/ MatToolbarModule, MatCardModule, MatButtonModule ], providers: [], bootstrap: [AppComponent] }) export class AppModule { }
我們為工具欄、卡片和按鈕組件導入模塊,並將它們添加到AppModule
的導入數組中。
接下來,打開src/app/app.component.html
文件,刪除其中的內容並添加:
<mat-toolbar color="primary"> <mat-toolbar-row> <span>JS-jargon</span> </mat-toolbar-row> </mat-toolbar> <main> <mat-card *ngFor="let item of items"> <mat-card-header> <mat-card-title>{{item.name}}</mat-card-title> </mat-card-header> <mat-card-content> {{item.description}} </mat-card-content> <mat-card-actions> <a mat-raised-button href="{{item.url}}" color="primary">More</a> </mat-card-actions> </mat-card> </main>
我們使用 Material 組件來創建 UI。 <mat-toolbar>
組件用於創建材質工具欄, <mat-card>
組件用於創建材質卡等。
當組件初始化時,我們遍歷由fetchData()
方法填充的items
數組,並將項目顯示為 Material 卡片。 每張卡片都包含名稱、描述和更多信息的鏈接(該鏈接使用mat-raised-button
指令設置為材質按鈕)。
這是應用程序的屏幕截圖:
構建生產應用程序
通常,在檢查您的應用程序的 PWA 功能時,您應該首先將其構建用於生產,因為大多數 PWA 功能都沒有在開發中添加。 例如,您不希望在開發中啟用服務工作者和緩存,因為您需要定期更新文件。
讓我們使用以下命令構建用於生產的應用程序:
$ ng build --prod
生產版本可從dist/pwademo
文件夾中獲得。 我們可以使用像http-server
這樣的工具來服務它。
首先,使用以下命令安裝http-server
:
$ npm i -g http-server
然後,您可以使用以下命令運行它:
$ cd dist/pwademo $ http-server -o
-o
選項將自動打開系統中的默認瀏覽器並導航到我們的 Web 應用程序可用的https://127.0.0.1:8080/
地址。
使用 Lighthouse 分析應用程序
現在讓我們使用 Lighthouse 分析我們的應用程序。 首先,啟動 Chrome 並訪問我們的應用程序地址https://127.0.0.1:8080/
。
接下來,打開Developer Tools或按Ctrl + Shift + I並單擊Audit面板。
您最好需要將Emulation設置為Mobile而不是Desktop來模擬移動環境。 接下來,單擊執行審核...藍色按鈕。 您將打開一個對話框,您需要在其中選擇要對 Web 應用程序執行的審計類型。 取消選中除Progressive Web App之外的所有類型,然後單擊運行審核按鈕。
等待 Lighthouse 生成報告。 這是此階段結果的屏幕截圖:
Lighthouse 執行一系列檢查,以驗證 PWA 清單指定的漸進式 Web 應用程序的各個方面。 我們得到36 ⁄ 100的初始分數,這是因為我們通過了一些審核。
我們的應用程序有7次失敗的審計,主要與 PWA 的核心方面Service Workers 、 Progressive Enhancement 、 HTTPS和Web App Manifest相關。
註冊 Service Worker
前兩個失敗的審計(“不註冊服務工作者”和“離線時不響應 200”)與服務工作者和緩存有關。 那麼什麼是服務人員?
Service Worker 是現代瀏覽器上可用的一項功能,可用作網絡代理,讓您的應用程序攔截網絡請求以緩存資產和數據。 這可用於實現 PWA 功能,例如離線支持和推送通知等。
要通過這些審核,我們只需要註冊一個 service worker 並使用它在本地緩存文件。 離線時,軟件應返回文件的本地緩存版本。 稍後我們將看到如何使用一個 CLI 命令添加它。
推薦閱讀:製作服務工作者:案例研究
漸進增強
第三次失敗的審核(“當 JavaScript 不可用時不提供回退內容”)與漸進增強有關,這是 PWA 的一個重要方面,它只是指 PWA 在不同瀏覽器上運行但提供高級功能的能力,如果他們有空。 PE 的一個簡單示例是使用<noscript>
HTML 標籤,它通知用戶需要啟用 JavaScript 以在未啟用的情況下運行應用程序:
<noscript> Please enable JavaScript to run this application. </noscript>
HTTPS
第四次失敗的審計(“不將 HTTP 流量重定向到 HTTPS”)與 HTTPS 相關,這也是 PWA 的核心方面(服務工作者只能從安全的來源提供服務,除了 localhost)。 “使用 HTTPS”審核本身被認為已通過 Lighthouse,因為我們正在審核 localhost,但是一旦您使用實際主機,您就需要 SSL 證書。 您可以從 Let's Encrypt、Cloudflare、Firebase 或 Netlify 等不同服務獲得免費 SSL 證書。
Web 應用清單
三個失敗的審核(“不會提示用戶安裝 Web 應用程序”、“未為自定義啟動畫面配置”和“地址欄與品牌顏色不匹配”)與缺少的Web 應用程序清單有關,該清單是JSON 格式的文件,提供 PWA 所需的名稱、描述、圖標和其他信息。 它允許用戶像本地應用程序一樣在主屏幕上安裝網絡應用程序,而無需通過應用程序商店。
您需要提供一個 Web 應用清單,並使用<link>
標記從index.html
文件中引用它,並將rel
屬性設置為manifest
。 接下來我們將看到如何使用一個 CLI 命令自動執行此操作。
實現 PWA 功能
Angular CLI v6 允許您將 PWA 功能快速添加到現有的 Angular 應用程序中。 您只需在終端中從項目的根目錄運行以下命令,即可將您的應用程序轉換為 PWA:
$ ng add @angular/pwa
該命令會自動將 PWA 功能添加到我們的 Angular 應用程序中,例如:
- 一個
manifest.json
文件, -
src/assets/icons
文件夾中不同大小的圖標, -
ngsw-worker.js
服務工作者。
打開包含生產版本的dist/
文件夾。 您會找到各種文件,但讓我們專注於我們上面提到的與 PWA 功能相關的文件:
添加了manifest.json
文件,其中包含以下內容:
{ "name": "pwademo", "short_name": "pwademo", "theme_color": "#1976d2", "background_color": "#fafafa", "display": "standalone", "scope": "/", "start_url": "/", "icons": [ { "src": "assets/icons/icon-72x72.png", "sizes": "72x72", "type": "image/png" }, { "src": "assets/icons/icon-96x96.png", "sizes": "96x96", "type": "image/png" }, { "src": "assets/icons/icon-128x128.png", "sizes": "128x128", "type": "image/png" }, { "src": "assets/icons/icon-144x144.png", "sizes": "144x144", "type": "image/png" }, { "src": "assets/icons/icon-152x152.png", "sizes": "152x152", "type": "image/png" }, { "src": "assets/icons/icon-192x192.png", "sizes": "192x192", "type": "image/png" }, { "src": "assets/icons/icon-384x384.png", "sizes": "384x384", "type": "image/png" }, { "src": "assets/icons/icon-512x512.png", "sizes": "512x512", "type": "image/png" } ] }
如您所見,添加的manifest.json
文件包含 PWA 所需的所有信息,例如名稱、描述和start_url
等。
manifest.json
文件,鏈接到不同大小的圖標,這些圖標也自動添加到assets/icons
文件夾中。 當然,一旦您準備好構建 PWA 的最終版本,您就需要用自己的圖標更改這些圖標。
在index.html
文件中, manifest.json
文件通過以下方式引用:
<link rel="manifest" href="manifest.json">
ngsw-worker.js
文件也被自動添加,其中包含 service worker。 安裝這個 service worker 的代碼會自動插入到src/app/app.module.ts
文件中:
... import { ServiceWorkerModule } from '@angular/service-worker'; @NgModule({ declarations: [ AppComponent ], imports: [ ... ServiceWorkerModule.register('/ngsw-worker.js', { enabled: environment.production }) ],
@angular/service-worker
由ng add
命令安裝並作為依賴項添加到pwademo/package.json
:
"dependencies": { ... "@angular/service-worker": "^6.1.0" }
Service Worker 構建支持也在 CLI 中啟用。 在angular.json
文件中添加了一個"serviceWorker": true
配置選項。
在index.html
文件中添加了一個值為#1976d2
theme_color
theme-color
元標記(它也對應於manifest.json
文件中的主題顏色值):
<meta name="theme-color" content="#1976d2">
主題顏色告訴瀏覽器為地址欄等 UI 元素著色的顏色。
將主題顏色添加到index.html
和manifest.json
文件修復了地址欄匹配品牌顏色審核。
Service Worker 配置文件
另一個文件src/ngsw-config.json
已添加到項目中,但它不是 PWA 必需的文件。 它是一個配置文件,允許您指定 Angular 服務工作者應該緩存哪些文件和數據 URL,以及它應該如何更新緩存的文件和數據。 您可以從官方文檔中找到有關此文件的所有詳細信息。
注意:在撰寫本文時,使用最新的6.1.3之前的ng add @angular/pwa
命令將失敗並出現以下錯誤: Path “/ngsw-config.json” already exists
,因此目前的解決方案是降級@angular/cli
和@angular/pwa
到版本6.0.8 。
只需在項目中運行以下命令:
$ npm i @angular/[email protected] $ ng i @angular/[email protected] $ ng add @angular/pwa
現在讓我們針對本地託管的本地 PWA 重新運行審計。 這是新的 PWA 分數:
Angular CLI 不會自動添加我們在漸進增強部分中提到的 JavaScript 後備代碼,因此請打開src/index.html
文件並添加它:
<noscript> Please enable JavaScript to run this application. </noscript>
接下來,重建您的應用程序並重新運行審核。 這是現在的結果:
我們只有一項與 HTTPS 重定向相關的審核失敗。 我們需要託管應用程序並配置 HTTP 到 HTTPS 重定向。
現在讓我們針對 PWA 的託管和安全版本運行審計。
我們得到100 ⁄ 100的分數,這意味著我們已經成功實施了 PWA 的所有核心原則。
您可以從此 GitHub 存儲庫獲取此演示 PWA 的最終代碼。
結論
在本教程中,我們構建了一個簡單的 Angular 應用程序,並使用 Angular CLI 將其轉換為 PWA。 我們使用 Google 的 Lighthouse 來審核我們的應用程序的 PWA 功能,並解釋 PWA 的各種核心原則,例如用於添加離線支持和推送通知的Service Workers 。 用於啟用添加到主屏幕和啟動屏幕功能、漸進增強以及HTTPS的Web 清單文件。
您可能還需要手動檢查其他突出顯示的項目(在“要手動檢查的其他項目”部分下),但 Lighthouse 不會自動檢查。 Google 的基準 PWA 清單要求這些檢查。 它們不會影響 PWA 分數,但手動驗證它們很重要。 例如,您需要確保您的網站可以跨瀏覽器運行,並且每個頁面都有一個 URL,這對於在社交媒體上的可共享性很重要。
由於 PWA 還涉及其他方面,例如更好的感知性能和可訪問性,您還可以使用 Lighthouse 來審核您的 PWA(或任何一般網站)的這些方面並根據需要進行改進。