Angular v16 來了!

六個月前,我們將獨立 API從開發人員預覽中升級,從而在 Angular 的簡單性和開發人員體驗方面達到了一個重要的里程碑。今天,我們很高興地宣佈,我們將繼續 Angular Momentum,推出自 Angular 首次推出以來最大的版本;在反應性、服務器端渲染和工具方面取得巨大飛躍。所有這一切都伴隨着跨功能請求的數十項生活質量改進,在 GitHub 上獲得了 2,500 多個贊!

 

Angular v16 版本的視覺效果在筆記本電腦上顯示文本“v16”,圖像右側有 Angular 徽標。

Angular v16 版本

 

 

重新思考反應性

作爲 v16 版本的一部分,我們很高興與大家分享一個全新的 Angular 反應模型的開發者預覽,它顯着改善了性能和開發者體驗。

完全向後兼容並可與當前系統互操作,並支持

最初的GitHub 討論獲得了 682 條評論,從那時起我們分享了一系列 RFC,收到了超過 1,000 條評論!

在 v16 中,您可以找到一個新的信號庫,它是@angular/coreRxJS 互操作包的一部分@angular/core/rxjs-interop,框架中的完整信號集成將於今年晚些時候推出。

角度信號

Angular 信號庫允許你定義響應值並表達它們之間的依賴關係。您可以在相應的 RFC中瞭解有關庫屬性的更多信息。這是一個如何將它與 Angular 一起使用的簡單示例:

@Component({
selector: 'my-app',
standalone: true,
template: `
{{ fullName() }} <button (click)="setName('John')">Click</button>
`,
})
export class App {
firstName = signal('Jane');
lastName = signal('Doe');
fullName = computed(() => `${this.firstName()} ${this.lastName()}`);

constructor() {
effect(() => console.log('Name changed:', this.fullName()));
}

setName(newName: string) {
this.firstName.set(newName);
}
}

上面的代碼片段創建了一個計算值fullName,它取決於信號firstNamelastName。我們還聲明瞭一個效果,每當我們更改它讀取的任何信號的值時,回調都會執行——在本例中,fullName這意味着它也傳遞地依賴於firstNamelastName

當我們將 的值設置firstName爲“John”時,瀏覽器將登錄到控制檯:

"Name changed: John Doe"

RxJS 互操作性

@angular/core/rxjs-interop作爲 v16 版本的一部分,您將能夠通過開發人員預覽中的函數輕鬆地將信號“提升”到可觀察對象!

以下是將信號轉換爲可觀察信號的方法:

import { toObservable, signal } from '@angular/core/rxjs-interop';

@Component({...})
export class App {
count = signal(0);
count$ = toObservable(this.count);

ngOnInit() {
this.count$.subscribe(() => ...);
}
}

…這是一個示例,說明如何將可觀察對象轉換爲信號以避免使用異步管道:

import {toSignal} from '@angular/core/rxjs-interop';

@Component({
template: `
<li *ngFor="let row of data()"> {{ row }} </li>
`
})
export class App {
dataService = inject(DataService);
data = toSignal(this.dataService.data$, []);
}

Angular 用戶通常希望在相關主題完成時完成流。以下說明性模式非常常見:

destroyed$ = new ReplaySubject<void>(1);

data$ = http.get('...').pipe(takeUntil(this.destroyed$));

ngOnDestroy() {
this.destroyed$.next();
}

我們正在引入一個名爲 的新 RxJS 運算符takeUntilDestroy,它將此示例簡化爲以下內容:

data$ = http.get('…').pipe(takeUntilDestroyed());

默認情況下,此運算符將注入當前清理上下文。比如在組件中使用,會使用組件的生命週期。

takeUntilDestroy當您想將 Observable 的生命週期與特定組件的生命週期聯繫起來時,它特別有用。

信號的後續步驟

接下來,我們將研究基於信號的組件,這些組件具有一組簡化的生命週期掛鉤,以及另一種更簡單的聲明輸入和輸出的方法。我們還將致力於更完整的示例和文檔集。

Angular 存儲庫中最受歡迎的問題之一是“建議:作爲可觀察輸入”。幾個月前,我們迴應說我們希望支持這個用例,作爲框架中更大努力的一部分。我們很高興與大家分享,今年晚些時候我們將推出一項功能,支持基於信號的輸入——您將能夠通過互操作包將輸入轉換爲可觀察對象!

服務器端渲染和水合作用增強

根據我們的年度開發人員調查,服務器端渲染是 Angular 改進的首要機會。在過去的幾個月裏,我們與Chrome Aurora 團隊合作改進了水化和服務器端渲染的性能和 DX。今天我們很高興分享完整應用程序無損水化的開發者預覽!

 

Angular hydration 的橫幅,在 Angular 徽標上帶有藍色水圖案的 hydration 文本

在新的完整應用程序非破壞性水合作用中,Angular 不再從頭開始重新渲染應用程序。相反,該框架在構建內部數據結構時查找現有的 DOM 節點,並將事件偵聽器附加到這些節點。

好處是:

  • 最終用戶頁面上沒有內容閃爍
  • 在某些情況下更好的Web Core Vitals
  • 面向未來的架構,支持使用我們將在今年晚些時候發佈的原語進行細粒度代碼加載。目前,這在漸進式懶惰路線水合作用中浮出水面
  • 只需幾行代碼即可輕鬆與現有應用程序集成(請參見下面的代碼片段)
  • ngSkipHydration在執行手動 DOM 操作的組件的模板中逐步採用水合作用和屬性

在早期測試中,我們看到Largest Contentful Paint的改進高達 45%,並具有完整的應用程序水合作用!

 

 

要開始使用它就像在您的中添加幾行一樣簡單main.ts

import {
bootstrapApplication,
provideClientHydration,
} from '@angular/platform-browser';

...

bootstrapApplication(RootCmp, {
providers: [provideClientHydration()]
});

您可以在文檔中找到有關其工作原理的更多詳細信息。

新的服務器端渲染功能

作爲 v16 版本的一部分,我們還更新了 Angular Universal 的 ng add schematics,使您能夠使用獨立 API 將服務器端渲染添加到項目中。我們還爲內聯樣式引入了對更嚴格的內容安全策略的支持

水合作用和服務器端渲染的後續步驟

我們計劃在這裏做更多的事情,v16 中的工作只是墊腳石。在某些情況下,有機會延遲加載對頁面不重要的 JavaScript,並在以後混合相關組件。這種技術被稱爲部分水化,我們接下來將對其進行探索。

自從 Qwik 從 Google 的封閉源代碼框架 Wiz 中普及了可恢復性的想法後,我們收到了很多對 Angular 中此功能的請求。可恢復性肯定在我們的關注範圍內,我們正在與 Wiz 團隊密切合作探索這個領域。我們對其帶來的對開發人員體驗的限制持謹慎態度,評估不同的權衡,並會在我們取得進展時及時通知您。

您可以在“ Angular 中服務器端渲染的下一步是什麼”中閱讀更多關於我們未來計劃的信息。

改進了獨立組件、指令和管道的工具

Angular 是數百萬開發人員用於許多關鍵任務應用程序的框架,我們認真對待重大變化。幾年前我們開始探索獨立的 API ,在 2022 年我們在開發者預覽版下發布了它們。現在,經過一年多的收集反饋和迭代 API,我們希望鼓勵更廣泛的採用!

爲了支持開發人員將他們的應用程序轉換爲獨立 API,我們開發了遷移示意圖和獨立遷移指南。進入項目目錄後運行:

ng generate @angular/core:standalone

原理圖將轉換您的代碼,刪除不必要的NgModules類,並最終更改項目的引導程序以使用獨立的 API。

獨立 ng 新集合

作爲 Angular v16 的一部分,您可以從一開始就獨立創建新項目!要嘗試獨立原理圖的開發人員預覽,請確保您使用的是 Angular CLI v16 並運行:

ng new --standalone

您將獲得一個更簡單的項目輸出,沒有任何NgModules. 此外,項目中的所有生成器都將生成獨立的指令、組件和管道!

配置 Zone.js

在獨立 API 首次發佈後,我們從開發人員那裏得知您希望能夠使用新bootstrapApplicationAPI配置 Zone.js。

我們爲此添加了一個選項provideZoneChangeDetection

bootstrapApplication ( App , { providers : [ provideZoneChangeDetection ({ eventCoalescing : true })] });

推進開發人員工具

現在,讓我們分享 Angular CLI 和語言服務的一些功能亮點。

基於 esbuild 的構建系統的開發者預覽版

一年多以前,我們宣佈我們正在努力爲 Angular CLI 中的 esbuild 提供實驗性支持,以使您的構建速度更快。今天,我們很高興地與大家分享,在 v16 中,我們基於 esbuild 的構建系統進入了開發者預覽版!早期測試表明,冷生產構建的改進超過 72%。

 

顯示 Vite 和 esbuild 徽標的圖像

基於 esbuild 的構建器的開發者預覽版

我們ng serve現在使用 Vite 作爲開發服務器,而 esbuild 爲您的開發和生產構建提供支持!

我們要強調的是 Angular CLI 完全依賴 Vite 作爲開發服務器。爲了支持選擇器匹配,Angular 編譯器需要維護組件之間的依賴圖,這需要與 Vite 不同的編譯模型。

你可以通過更新你的:來嘗試 Vite + esbuild angular.json

... "architect" :  {  "build" :  {  /* 添加 esbuild 後綴 */  "builder" :  "@angular-devkit/build-angular:browser-esbuild" , ...

接下來我們將解決對 i18n 的支持,然後再從開發人員預覽中畢業這個項目。

使用 Jest 和 Web Test Runner 進行更好的單元測試

根據 Angular 和更廣泛的 JavaScript 社區中的開發人員調查,Jest是最受歡迎的測試框架和測試運行器之一。我們收到了大量支持 Jest 的請求,由於不需要真正的瀏覽器,因此複雜性降低了。

今天,我們很高興地宣佈我們將引入實驗性的 Jest 支持。在未來的版本中,我們還將現有的Karma項目移至Web Test Runner,以繼續支持基於瀏覽器的單元測試。對於大多數開發人員來說,這將是一個空操作。

npm install jest --save-dev您可以通過安裝 Jest並更新文件來在新項目中試驗 Jest angular.json

{
"projects": {
"my-app": {
"architect": {
"test": {
"builder": "@angular-devkit/build-angular:jest",
"options": {
"tsConfig": "tsconfig.spec.json",
"polyfills": ["zone.js", "zone.js/testing"]
}
}
}
}
}
}

 

您可以在我們最近的博客文章中瞭解有關我們未來單元測試策略的更多信息。

模板中的自動完成導入

您有多少次在模板中使用組件或管道從 CLI 或語言服務中獲取您實際上沒有導入相應實現的錯誤?我打賭很多次!

語言服務現在允許自動導入組件和管道。

 

顯示 Angular 語言服務的自動導入功能的 Gif。

Angular 語言服務自動導入

Gif 顯示了 VSCode 中 Angular 語言服務的自動導入功能

還有更多!

在 v16 中,我們還啓用了對 TypeScript 5.0 的支持,支持ECMAScript裝飾,消除了 ngcc 的開銷,在獨立應用程序中添加了對service workersapp shell的支持,擴展了CLI 中的 CSP 支持等等

改善開發者體驗

除了我們關注的大型計劃外,我們還致力於帶來高度要求的功能。

所需輸入

自從我們在 2016 年引入 Angular 以來,如果您不爲特定輸入指定值,就不可能出現編譯時錯誤。由於 Angular 編譯器在構建時執行檢查,因此更改在運行時增加了零開銷。多年來,開發人員一直 要求 功能 ,我們得到了一個強烈的跡象,表明這將非常方便

在 v16 中,您現在可以根據需要標記輸入:

@Component (...) export  class  App { @Input ({ required : true }) title : string = '' ; }

將路由器數據作爲組件輸入傳遞

路由器的開發人員體驗一直在快速發展。GitHub 上一個流行的功能請求是要求能夠將路由參數綁定到相應組件的輸入。我們很高興地告訴大家,此功能現已作爲 v16 版本的一部分提供!

現在您可以將以下數據傳遞給路由組件的輸入:

  • 路由數據——解析器和數據屬性
  • 路徑參數
  • 查詢參數

以下是如何從路由解析器訪問數據的示例:

const routes = [ { path : 'about' , loadComponent : import ( './about' ), resolve : { contact : () =>  getContact () } } ]; @Component (...) export  class  About { // 將“contact”的值傳遞給contact input  @Input () contact?: string ; }

CSP 對內聯樣式的支持

Angular 在組件樣式的 DOM 中包含的內聯樣式元素違反了默認的style-src 內容安全策略 (CSP)。要解決這個問題,它們應該包含一個nonce屬性,或者服務器應該在 CSP 標頭中包含樣式內容的散列。儘管在谷歌我們沒有找到針對此漏洞的有意義的攻擊向量,但許多公司執行嚴格的 CSP,導致對 Angular 存儲庫的功能請求的流行。

nonce在 Angular v16 中,我們實現了一個跨越框架、Universal、CDK、Material 和 CLI 的新功能,它允許您爲 Angular 內聯的組件的樣式指定一個屬性。有兩種方法可以指定隨機數:使用屬性ngCspNonce或通過CSP_NONCE注入令牌。

如果您有權訪問可以將兩者添加到標頭和構建響應時的ngCspNonce服務器端模板,則該屬性很有用。nonceindex.html

<html>
<body>
<app ngCspNonce="{% nonce %}"></app> 
</body>
</html>

另一種指定隨機數的方法是通過CSP_NONCE注入令牌。如果您有權在運行時訪問nonce並且希望能夠緩存,請使用此方法index.html

import {bootstrapApplication, CSP_NONCE} from '@angular/core';
import {AppComponent} from './app/app.component';

bootstrapApplication(AppComponent, {
providers: [{
provide: CSP_NONCE,
useValue: globalThis.myRandomNonceValue
}]
});

靈活的 ngOnDestroy

Angular 的生命週期鉤子提供了強大的功能來插入應用程序執行的不同時刻。多年來的一個機會是實現更高的靈活性,例如,提供對OnDestroy 作爲 observable 的訪問。

在 v16 中,我們使 OnDestroy 可注入,從而實現開發人員一直要求的靈活性。這個新功能允許您注入DestroyRef對應的組件、指令、服務或管道——並註冊onDestroy生命週期掛鉤。可以DestroyRef在注入上下文中的任何地方注入,包括組件外部——在這種情況下,onDestroy當相應的注入器被銷燬時,鉤子就會被執行:

import { Injectable, DestroyRef } from '@angular/core';

@Injectable(...)
export class AppService {
destroyRef = inject(DestroyRef);

destroy() {
this.destroyRef.onDestroy(() => /* cleanup */ );
}
}

自閉標籤

我們最近實現的一項非常受歡迎的功能允許您爲 Angular 模板中的組件使用自閉合標籤。這是一個小的開發人員體驗改進,可以節省您的輸入時間!

現在你可以替換:

< super-duper-long-component-name [ prop ]= "someVar" > </ super-duper-long-component-name >

有了這個:

< super-duper-long-component-name [ prop ]= "someVar" />

更好、更靈活的組件

在過去的幾個季度中,我們與 Google 的 Material Design 團隊密切合作,爲 Web 和 Angular Material 提供參考 Material 3 實現。我們在 2022 年發佈的基於 Web 的 MDC 組件爲這項工作奠定了基礎。

作爲下一步,我們正努力在今年晚些時候推出一個基於令牌的富有表現力的主題 API,以實現 Angular 材質組件的更高定製化。

提醒一下,我們將在 v17 中刪除遺留的、非基於 MDC 的組件。請確保您按照我們的遷移指南遷移到最新版本。

繼續我們的無障礙倡議

遵循 Google 的使命,Angular 可讓您爲所有人構建 Web 應用程序!這就是爲什麼我們不斷投資以提高Angular CDK 和 Material 組件的可訪問性。

社區貢獻亮點

我們要強調的社區引入的兩個功能是:

超過 175 人在 GitHub 上爲 v16 做出了貢獻,還有數千人通過博客文章、演講、播客、視頻、對反應性 RFC 的評論等做出了貢獻。

我們非常感謝所有幫助我們使這個版本變得特別的人。

讓我們一起保持勢頭!

版本 16 是明年 Angular 的反應性和服務器端渲染未來改進的墊腳石。我們將通過在開發人員體驗和性能方面進行創新來推動 Web 向前發展,同時讓您能夠爲每個人構建!

你可以成爲 Angular Momentum 的一員,通過在即將到來的 RFC、調查或社交媒體中分享你的想法來幫助我們塑造框架的未來。

感謝您成爲 Angular 社區的一員。我們迫不及待地想讓您嘗試這些功能!

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