Angular v8 發佈!來看看有什麼新功能

翻譯:瘋狂的技術宅

原文:https://jaxenter.com/whats-ne...html

未經容許嚴禁轉載前端

clipboard.png

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

Angular 8 剛剛發佈!git

徹底按照計劃,沒有任何意外:框架和 CLI 的更新能夠經過 ng update 完成,其新功能是一個受歡迎的補充,符合「演化而不是革命」的座右銘。程序員

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

先瞅一眼 Ivy

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

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

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

clipboard.png

使用與不使用 Ivy 時的 hello world 程序的 Bundle 大小(來源:由Brad Green和Igor Minar撰寫的 ngconf 2019 主題演講)segmentfault

感謝差別加載(以下所示),bundle 大小已經能夠當即獲得優化。瀏覽器

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

若是你想嘗試 Ivy,能夠經過 enable-ivy 開關生成一個新項目:

ng new ivy-project --enable-ivy

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

"angularCompilerOptions": { 
        "enableIvy": true 
}

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

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

ng serve --aot

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

Web worker

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

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

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

clipboard.png

n 皇后問題的一種解決方案

計算棋盤上全部可能的解決方案的算法被認爲是計算密集型的。雖然對有 8 行和 8 列的常規棋盤的計算至關快,可是普通計算機從 12×12 格開始就達到了其極限。當前最高記錄是解決具備 27 x 27 格的解決方案。俄羅斯的超級計算機完成了此任務。

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

ng generate worker n-queens

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

worker自己只包含 message 事件的事件監聽器:

import nQueens from './n-queens';

addEventListener('message', ({ data }) => {
  const result = nQueens(data.count);
  postMessage(result, undefined);
});

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

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

const count = parseInt(this.count, 10);

const worker = new Worker('../logic/n-queens.worker', {
    type: 'module' // Worker uses EcmaScript modules
});

worker.postMessage({count});

worker.addEventListener('message', (event) => {
  // tslint:disable-next-line: no-console
  console.debug('worker result', event.data);

  // Update chessboard
  this.processResult(event.data);
});

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

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

完整的實現包含在做者的樣本集[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 中輸入版本上限,以下所示:

"target": "es2015"

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

> 0.5%
last 2 versions
Firefox ESR
not dead
IE 9-11

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

clipboard.png

構建差別加載

這個過程的缺點顯而易見:構建過程所需的時間加倍。

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

<script src="main-es2015.js" type="module"></script>

<script src="main-es5.js" nomodule></script>

ng build 相比,其餘全部 CLI 命令僅使用上限。在上圖中所示的這種狀況下,是 ECMAScript 2015。出於效率緣由,會發生這種狀況:特別是在調試和測試期間,開發人員但願儘快看到結果,而不須要等待第二次構建。

延遲加載

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

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

「#」號以前的值表示通向模塊實現的文件的路徑;以後的值表明其中包含的類。這種寫做風格也適用於 Angular 8,可是已經被棄用了,如今支持動態 ECMAScript 導入:

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

新的書寫風格中仍然包含文件名做爲魔術值。可是因爲許多IDE支持導入,所以無效值將當即返回錯誤。

ViewChild 和 ContentChild 中的重大變化

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

因爲這種行爲十分使人困惑,因此如今組件必須指定什麼時候應該進行解決:

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

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

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

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

ngUpgrade的新功能

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

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

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

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

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

結論

Angular團隊再次表達了本身的觀點:遷移到新的 Angular 版本很容易,而且不須要進行大的更改。使得使用 Google 的 SPA 框架更加溫馨。若是舊版瀏覽器不受支持或不支持單獨的 bundle 包,則差別加載會爲進一步優化 bundles 包。 Web worker 支持代表愈來愈多的計算密集型任務開始進入瀏覽器。如今能夠嘗試用 Ivy 邁出第一步。


本文首發微信公衆號:前端先鋒

歡迎掃描二維碼關注公衆號,天天都給你推送新鮮的前端技術文章

歡迎掃描二維碼關注公衆號,天天都給你推送新鮮的前端技術文章


歡迎繼續閱讀本專欄其它高贊文章:


相關文章
相關標籤/搜索