概覽
眾所周知, angular
應用在可執行之前, angular
應用中的元件和模板必須被轉化為可以被瀏覽器識別的javascript
程式碼, 而這種轉化正是通過angualr
自身的編譯器所執行的.
angular提供了兩種編譯方式, 即AOT
(預編譯)和JIT
(即使編譯), 其中JIT
為預設的編譯方式
AOT即 Ahead of time
, 是指在構建時進行編譯, 即在服務端即完成了編譯
JIt即 Just-in-Time
, 在執行期間編譯該應用,也就是在應用載入時。
AOT vs JIT
實際上只有一個編譯器,兩者的區別只是編譯的時機和工具不同
JIT編譯導致執行期間的效能損耗。 由於需要在瀏覽器中執行這個編譯過程,檢視需要花更長時間才能渲染出來。 由於應用包含了Angular編譯器以及大量實際上並不需要的庫程式碼,所以檔案體積也會更大。 更大的應用需要更長的時間進行傳輸,載入也更慢。
編譯可以發現一些元件模板繫結錯誤。JIT編譯在執行時才揭露它們,那樣有點太晚了。
而預編譯(AOT)會在構建時編譯,這樣可以在早期截獲模板錯誤,提高應用效能。
#JiT編譯模式的流程
一個典型的jiT
應用的開發流程大概是:
- 使用
TypeScript
開發Angular應用 - 使用
tsc
來編譯這個應用的ts程式碼 - 打包
- 壓縮
- 部署
一旦把app部署好了,並且使用者在瀏覽器中開啟了這個app,下面這些事情會逐一進行:
- 瀏覽器下載js程式碼
Angular
啟動Angular
在瀏覽器中開始JiT
編譯的過程,例如生成app中各個元件的js程式碼- 應用頁面得以渲染
相對的,使用AoT
模式的應用的開發流程是:
- 使用
TypeScript
開發Angular
應用 - 使用
ngc
來編譯應用- 使用
Angular
編譯器對模板進行編譯,生成TypeScript
程式碼 TypesScript
程式碼編譯為JavaScript
程式碼
- 使用
- 打包
- 壓縮
- 部署
雖然前面的過程稍稍複雜,但是使用者這一側的事情就變簡單了:
- 下載所有程式碼
Angular
啟動- 應用頁面得以渲染
概括起來,Angular
中的Jit
和AoT
的主要區別是:
- 編譯過程發生的時機
JiT
生成的是JS
程式碼,而AoT
生成的是TS
程式碼。這主要是因為JiT
是在瀏覽器中進行的,它完全沒必要生成TS
程式碼,而是直接生產了JS
程式碼。
深入AOT編譯
AOT編譯的配置
安裝npm
依賴
npm install @angular/compiler-cli @angular/platform-server --save
複製程式碼
把下列npm便利指令碼新增到package.json中,以便用一條命令就可以完成編譯
"build:aot": "ngc -p tsconfig-aot.json
複製程式碼
用@angular/compiler-cli
包中提供的ngc
編譯器來代替TypeScript
編譯器(tsc)。
配置tsconfig-aot.json
檔案
只需將
tsconfig.json
檔案複製過來進行修改即可
{
"compilerOptions": {
"target": "es5",
"module": "es2015",
"moduleResolution": "node",
"sourceMap": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"lib": ["es2015", "dom"],
"noImplicitAny": true,
"suppressImplicitAnyIndexErrors": true,
"typeRoots": [
"./node_modules/@types/"
]
},
"files": [
"src/app/app.module.ts",
"src/main.ts"
],
"angularCompilerOptions": {
"genDir": "aot",
"skipMetadataEmit" : true
}
}
複製程式碼
compilerOptions
部分只修改了一個屬性:**把module設定為es2015
(為後面搖樹優化做準備)
ngc
區真正新增的內容是底部的angularCompilerOptions
。 它的genDir
屬性告訴編譯器把編譯結果儲存在新的aot
目錄下
"skipMetadataEmit" : true
屬性阻止編譯器為編譯後的應用生成後設資料檔案。 當輸出成TypeScript檔案時,後設資料並不是必須的,因此不需要包含它們。
啟動AOT編譯:
node_modules/.bin/ngc -p tsconfig-aot.json
複製程式碼
編譯完成後生成了一堆NgFactory
檔案,不要編輯這些NgFactory!重新編譯時會替換這些檔案.
改變引導方式main.ts
檔案
從platformBrowserDynamic.bootstrap
改成使用platformBrowser().bootstrapModuleFactory
並把AppModuleNgFactory
的AOT編譯結果傳給它。
import { platformBrowser } from `@angular/platform-browser`;
import { AppModuleNgFactory } from `../aot/src/app/app.module.ngfactory`;
console.log(`Running AOT compiled`);
platformBrowser().bootstrapModuleFactory(AppModuleNgFactory);
複製程式碼
搖樹優化(Tree shaking)
搖樹優化是指通過跟蹤import
和export
語句來對應用進行靜態分析,遍歷依賴圖譜,並且搖掉用不到的程式碼,通過移除原始碼和庫程式碼中用不到的部分,搖樹優化可以大幅縮減應用的下載體積
搖樹優化能夠在我們最終的Bundle
中移除掉我們應用中沒有使用到的程式碼。這是減少應用程式佔用空間的最有效的技術之一。
目前webpack2已經支援tree shaking
, 官網介紹的是Rollup在angular中的使用
開發器使用JIT, 產品期使用AOT
目前,AOT編譯和搖樹優化對開發來說,佔用的時間太多了。這將在未來得到改變。 當前的最佳實踐是在開發器使用JIT編譯,然後在釋出產品前切換到AOT編譯