Angular v8 發佈!來看看有什麼新功能[每日前端夜話0x7A]

Angular v8 發佈!來看看有什麼新功能[每日前端夜話0x7A]

瘋狂的技術宅 前端先鋒

每日前端夜話0x7A
每日前端夜話,陪你聊前端。
每天晚上18:00準時推送。
正文共:3332 字
預計閱讀時間: 8 分鐘
翻譯:瘋狂的技術宅
來源:jaxenter





Angular v8 發佈!來看看有什麼新功能[每日前端夜話0x7A]

Angular

Angular 8 終於來了,包括 Ivy 的預覽、service worker 支持,差異化加載以及一些錦上添花的東西。 Manfred Steyer 解釋了最新 Angular 版本中最重要的變化。

Angular 8 剛剛發佈!

完全按照計劃,沒有任何意外:框架和 CLI 的更新可以通過 ng update 完成,其新功能是一個受歡迎的補充,符合“演化而不是革命”的座右銘。

在本文中,我將介紹 Angular 8 和 Angular CLI 8 的最重要的新功能。我在文中的例子可以在 GitHub 上找到。

先瞅一眼 Ivy


Ivy 是 Angular 世界下一個望眼欲穿的大新聞,它是新的 Angular 編譯器,也是新的渲染管道。Ivy 有可能產生相當小 bundle,它使漸進式編譯更容易,也是 Angular 領域未來創新的基礎。

由於 Angular 大量的底層部分已經爲此進行了更改,因此 Angular 團隊特別注意與以前的 Angular 版本的兼容性:在切換到 Ivy 之後,現有的程序應該能夠像以前一樣工作。在一切正常的前提下,能夠得到明顯更小的 bundles 應該就足夠了。這並非是他們大發善心,而是因爲 Google 有 600 多個以 Angular 爲基礎的應用程序 —— 儘管是謠傳,但實際數字要高得多。

在 Angular 8 中 Ivy 的預覽版現在可供測試。此版本的目標是獲得早期反饋。因此,Angular 團隊建議不要把 Ivy 用於生產環境,而是繼續使用經典視圖引擎(圖1)。

Angular v8 發佈!來看看有什麼新功能[每日前端夜話0x7A]
使用與不使用 Ivy 時的 hello world 程序的 Bundle 大小(來源:由Brad Green和Igor Minar撰寫的 ngconf 2019 主題演講)
感謝差異加載(如下所示),bundle 大小已經可以立即得到優化。

正如 Google Angular 團隊背後的技術總監 Brad Green 在 ngconf 2019 中提到的那樣,Ivy 將在兼容模式下結合差異加載,顯着改善 bundle 的尺寸。尋求刺激的人可以嘗試一下未來的 Ivy API。該模式下有非常大的優化潛力。目前這些 API 仍然被標記爲私有。你可以通過查看它的類和函數來進行判斷:它們以特殊字符 ɵ 開頭。

如果你想嘗試 Ivy,可以通過 enable-ivy 開關生成一個新項目:


1ng new ivy-project --enable-ivy

這樣做的結果是 CLI 會在 tsconfig.app.json 中存儲以下配置條目:


 1"angularCompilerOptions": { 
 2        "enableIvy": true 
 3}

在更新到 Angular 8 之後,也可以手動添加此條目,以便用 Ivy 測試現有程序。

要在調試模式下運行程序,建議使用 AOT:


1ng serve --aot

此外,值得一提的是通過 ng build 創建的程序的大小。等到 Angular 9 發佈時 Ivy 最終應該會默認激活。在此之前,Angular 團隊計劃採取進一步措施以確保與舊版本的兼容性。

Web worker

根據定義,JavaScript 是單線程的。因此,對於數據調用等較大任務異步處理是很常見的。不用說,這對計算密集型沒有幫助。特別是那些廣泛的 JavaScript 解決方案變得越來越普遍,這就是爲什麼現在幾乎所有的瀏覽器都支持支持 Web worker。它們是瀏覽器在自己的線程中運行的腳本。通過發送消息與瀏覽器選項卡中的線程進行通信。

雖然 Web worker 本身與 Angular 無關,但在構建過程中必須考慮它們。目標是爲每個 Web worker 提供一個 bundle 包。此任務由新的 Angular CLI 完成。

爲了說明這個新功能,我將通過實現所謂的 “n 皇后問題”的 JavaScript 進行說明。這個想法是在棋盤上每行放一個皇后,而不能相互公雞。這意味着在同一行、列或對角線中不能有其他皇后。

Angular v8 發佈!來看看有什麼新功能[每日前端夜話0x7A]
n皇后問題的一種解決方案
計算棋盤上所有可能的解決方案的算法被認爲是計算密集型的。雖然對有 8 行和 8 列的常規棋盤的計算相當快,但是普通計算機從 12×12 格開始就達到了其極限。當前最高記錄是解決具有 27 x 27 格的解決方案。俄羅斯的超級計算機完成了此任務。

爲了將類似這樣的計算甩給後臺,我們必須首先用 Angular CLI 創建 一個Web worker:


1ng generate worker n-queens

此語句不僅爲 worker 創建文件,還爲構建過程和現有文件中的條目創建配置文件。如果同一文件夾包含具有公共文件擴展名 .component.ts 的同名組件,則 CLI 甚至會使用與 Web worker 通信的代碼對其進行豐富。

worker本身只包含 message 事件的事件監聽器:


1import nQueens from './n-queens';
2
3addEventListener('message', ({ data }) => {
4  const result = nQueens(data.count);
5  postMessage(result, undefined);
6});

當主線程向 worker 發送消息時會執行該事件。該參數包含從主線程發來的信息。在當前的情況下,它僅限於屬性 count ,它聲明瞭棋盤大小。在計算函數 nQueens 之後,事件監聽器通過 postMessage 將結果發送回主線程。*因此,瀏覽器在那裏觸發 message 事件。

Worker 類被應用於 using 組件來與此 worker 腳本交互:


 1const count = parseInt(this.count, 10);
 2
 3const worker = new Worker('../logic/n-queens.worker', {
 4    type: 'module' // Worker uses EcmaScript modules
 5});
 6
 7worker.postMessage({count});
 8
 9worker.addEventListener('message', (event) => {
10  // tslint:disable-next-line: no-console
11  console.debug('worker result', event.data);
12
13  // Update chessboard
14  this.proce***esult(event.data);
15});

組件通過 postMessage 向 worker 發送帶有所需棋盤大小的消息,從而觸發計算。它通過消息事件接收結果。

最後 CLI 負責將工作腳本正確的轉換和捆綁。由此啓動的 TypeScript 編譯器會通過它們的後綴 .worker.ts 來識別它們,它們在由 ng generate worker 生成的 tsconfig.worker.json 中註冊。爲了確保 CLI 在翻譯和捆綁主程序時不再考慮這些文件,ng generate worker 將相同的文件模式放在 tsconfig.app.json 的 exclude 部分中。

完整的實現包含在作者的樣本集[1]中。爲了便於說明,可以在主線程和 Web worker 中解決可用的 n 皇后問題。例如,當你爲 12 x 12 棋盤請求解決方案時,你將看到 UI 在第一種情況下會被凍結,而 worker 的後臺計算不會降低 UI 的可操作性。

差異加載

目前將程序編譯成舊 ECMAScript 5 代碼仍然是很常見的,因爲“古老的 JavaScript ”在今天仍然在到處運行。這意味着 IE 11 和 Google 搜索引擎後面的網絡爬蟲都可以執行這些代碼。

但是,新的 ECMAScript 2015 及其後續版本更加高效:這些版本允許更緊湊的 bundle 包,瀏覽器也可以更有效地解釋它們。

從版本 8 開始,CLI 包含一個名爲差異加載的功能。其背後的想法是提供兩組 bundle:一組基於 ECMAScript 5 並且針對較舊的瀏覽器,另一組基於較新的 ECMAScript 版本,例如 ECMAScript 2015,以此爲現代瀏覽器提供上述優勢。

要激活差異加載,你不用做太多的事情:只需要爲 ECMAScript 版本設置一個上限和下限。在 tsconfig.json 中輸入版本上限,如下所示:


1"target": "es2015"

另一方面,下限由瀏覽器列表來定義。根據市場份額等特定標準,它是一個用來標識許多支持的瀏覽器的文件。它們可以存儲在例如 browserslist 文件中,CLI 在生成新項目時同時會在 projectroot 中創建:


1> 0.5%
2last 2 versions
3Firefox ESR
4not dead
5IE 9-11

如下圖所示,browserslist 指向 ECMAScript 5 瀏覽器,條目爲 IE 9-11。因此,CLI 將下限確定爲此版本。如果 CLI 收到構建( ng build)指令,則將對兩個版本進行編譯和 bundling 過程:

Angular v8 發佈!來看看有什麼新功能[每日前端夜話0x7A]
構建差異加載
這個過程的缺點顯而易見:構建過程所需的時間加倍。

爲了使不同的瀏覽器可以決定要加載哪個版本的 bundle 包,他們在 index.html 添加中接受 script 的引用:指向 ECMAScript 5 包的那些引用會添加 nomodule。這可以使支持 ECMAScript 2015 及更新版本的瀏覽器忽略這些引用。另一方面,ECMAScript 2015+ bundle 包由 CLI 通過 type ="module" 實現。因此舊版瀏覽器將忽略這些腳本標記:


1<script src="main-es2015.js" type="module"></script>
2
3<script src="main-es5.js" nomodule></script>

與 ng build 相比,其他所有 CLI 命令僅使用上限。在上圖中所示的這種情況下,是 ECMAScript 2015。出於效率原因,會發生這種情況:特別是在調試和測試期間,開發人員希望儘快看到結果,而不需要等待第二次構建。

延遲加載

自 Angular 出現的第一天起,路由就支持延遲加載。到目前爲止,這是通過識別加載模塊的魔術值來完成的:


1{
2    path: 'lazy',
3    loadChildren: () => './lazy/lazy.module#LayzModule'
4}

“#”號之前的值表示通向模塊實現的文件的路徑;之後的值代表其中包含的類。這種寫作風格也適用於 Angular 8,但是已經被棄用了,現在支持動態 ECMAScript 導入:


1{
2    path: 'lazy',
3    loadChildren: () => import('./lazy/lazy.module').then(m => m.LazyModule)
4}

新的書寫風格中仍然包含文件名作爲魔術值。但是由於許多IDE支持導入,因此無效值將立即返回錯誤。

ViewChild 和 ContentChild 中的重大變化

ViewChild 和 ContentChild 的使用方式發生了重大變化,但遺憾的是,過去並不總是表現出一致的行爲。雖然它們在早期版本中被用於組件請求不在結構指令內的元素,如 ngIf 或 ngFor,但查詢結果已在 ngOnInit 中可用。否則,程序代碼或過早的可以在 ngAfterViewInit(或 ngAfterContentInit for ContentChild )中訪問它。對於以後因數據綁定而僅加載到 DOM 中的元素,程序代碼必須分別插入 ngAfterViewChecked 或 ngAfterContentChecked。

由於這種行爲十分令人困惑,所以現在組件必須指定何時應該進行解決:


1@ViewChild('info', { static: false })
2  paragraph: ElementRef;

如果 static 的值爲 true,則 Angular 會在初始化組件時嘗試查找該元素。這隻在不在結構指令中時纔有效。使用 static:false 時,在啓動或刷新視圖後進行解析。

ng update 命令 會自動嘗試在此處輸入正確的值。如果無法做到這一點,則會在其位置添加帶有 TODO 的註釋。

與相關裝飾器 ViewChildren 和 ContentChildren 的查詢不受此更改的影響。他們總是表現出 static:false 意義上的動態行爲。

ngUpgrade的新功能

到目前爲止,AngularJS 1.x 和 Angular 與 ngUpgrade 的混合操作中存在的一個問題是:兩個框架的路由有時一直在爭奪 URL。這導致了難以理解的副作用。爲了避免這種情況,可以使用相同的 Location 服務去訪問兩個版本框架中的 URL 。

爲實現這一目標,Angular 團隊擴展了Angular Location 服務的可能性,從而爲 AngularJS 中的 $location 提供了替代。

出於這個原因,在 Location 服務中添加了用於監視URL更改的新方法 onUrlChange 以及其他修改:


1export class AppComponent {
2  constructor(loc: Location, pLoc: PlatformLocation) {
3    loc.onUrlChange((url) => console.debug('url change', url));
4    console.debug('hostname: ', pLoc.hostname);
5  }
6}

PlatformLocation 服務提供對 URL 各個部分的附加訪問。有關如何使用 $location 替換的詳細描述(用於更好地交織兩個框架)可以在這裏找到。此外,你現在可以找到延遲加載 AngularJS 的想法,它基於前面提到的動態 ECMAScript 導入。

結論

Angular團隊再次表達了自己的觀點:遷移到新的 Angular 版本很容易,並且不需要進行大的更改。使得使用 Google 的 SPA 框架更加舒適。如果舊版瀏覽器不受支持或不支持單獨的 bundle 包,則差異加載會爲進一步優化 bundles 包。 Web worker 支持表明越來越多的計算密集型任務開始進入瀏覽器。現在可以嘗試用 Ivy 邁出第一步。

原文:https://jaxenter.com/whats-new-angular-8-159020.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章