Angular CLI 在後期的版本,提供了建立 app shell
的功能,何謂 app shell
,基本上就是透過 universal 的功能,先將首頁的畫面,產生靜態的 DOM 內容並新增到 index.html
的頁面中,並透過 app-shell component
(只是單純的 component) 顯示等待訊息。
為什麼要這樣子做,主要理由是讓使用者可以在第一時間得知他所開啟的網站,是有在執行的
那 Angular CLI 如何透過指令的方式,來完成建置 app shell 的效果呢?
操作步驟
為了方便展示,這裡我們重新建立一個全新的專案
1 | ng new shell-demo --routing |
當建立完成時,在執行以下的指令來新增 app-shell 的功能
1 | ng g app-shell --client-project <project name> --universal-project server-app |
需要換成自己要的專案名稱,已這裡的範例是 shell-demo
檢視變更檔案
-
angular.json
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16"server": {
"builder": "@angular-devkit/build-angular:server",
"options": {
"outputPath": "dist/shell-demo-server",
"main": "src/main.server.ts",
"tsConfig": "src/tsconfig.server.json"
}
},
"app-shell": {
"builder": "@angular-devkit/build-angular:app-shell",
"options": {
"browserTarget": "shell-demo:build",
"serverTarget": "shell-demo:server",
"route": "shell"
}
}在所指定的 client-project 下新增這兩個指令,而在之後的建置指令,會執行
app-shell
這個指令在 app-shell 指令內,分別設定了
browserTarget
和serverTarget
要執行的指令是什麼- 指定執行命令的方式
<projectName>:<architect 內的 指令名稱>:<command 內的 configuration>
例如shell-demo:build
- 指定執行命令的方式
-
main.ts
修改bootstrap
的時機點,會等 index.html 頁面內容讀取完成後再啟動 Angular App1
2
3
4document.addEventListener('DOMContentLoaded', () => {
platformBrowserDynamic().bootstrapModule(AppModule)
.catch(err => console.log(err));
}); -
app.module.ts
新增 universal 相關的 NgModule 設定1
2
3
4
5imports: [
BrowserModule.withServerTransition({ appId: 'serverApp' }),
AppRoutingModule,
RouterModule
],
比較重要的檔案變更就是上述的這幾的檔案
建置 app-shell 的方式
由於內建的 cli 指令並沒有針對建置 app-shell,所以必須透過 ng run
的方式來執行
1 | ng run shell-demo:app-shell |
- ng run 後面所接的指令,如我上面所描述的指令格式,例如
ng build
,對等同於ng run shell-demo:build
當執行完成後,在 dist
的資料夾可以看到兩個資料夾,一個是原本就會產生的網站資料夾,另外一個是 universal 用的資料夾
在輸出的 index.html
的內容,就會看到首頁的靜態 DOM 內容,這裡所產生的內容是從 app.module
所定義的 bootstrap
component 來的
當執行起來時,使用者就可以很快速地看到網站內容,然後再等 Angular 的應用程式被啟動起來。就對使用者來說,使用體驗就會變好了
執行結果
結論
透過 App-shell 對於使用者體驗,是有某種程度上的幫助,畢竟一開始就可以看到一些網站內容,而不是一個 loading 的畫面。