原文:https://blog.angular.dev/angular-v18-is-now-available-e79d5ac0affe
今天,我们很高兴与大家分享 Angular 发展的下一个里程碑!在过去的三个版本中,我们引入了许多新功能和改进。这次,我们专注于完善我们交付的工作,将许多新 API 升级为稳定版本,解决常见的开发者请求,并实验性地发布最理想的路线图项目之一:zoneless 域变更检测(zoneless change detection)。
此版本的亮点包括:
- 对 zoneless 变更检测的实验支持
- Angular.dev 现在是 Angular 开发人员的新家
- Material 3、可延迟视图、内置控制流现已稳定并包含一系列改进
- 服务器端渲染改进,例如 i18n 水合支持、更好的调试、Angular Material 中的水合支持以及由与 Google 搜索相同的库提供支持的事件重播。
不断演变的变化检测
从历史上看,一个名为 zone.js 的库负责触发 Angular 的变更检测。该库存在许多开发体验和性能缺点。多年来,我们一直在努力寻找一种不依赖 zone.js 的 Angular 使用方式,并且我们非常高兴能够分享第一个用于 zoneless 的实验性 API!
从今天开始,您可以尝试 Angular 中的实验性zoneless 支持!将 provideExperimentalZonelessChangeDetection 添加到您的应用程序引导程序中:
bootstrapApplication(App, {
providers: [
provideExperimentalZonelessChangeDetection()
]
});
添加提供后,从 angular.json 中的 polyfill 中删除 zone.js 。
展望未来,Zoneless 为开发人员打开了许多大门:
- 提高微前端的可组合性以及与其他框架的互操作性
- 更快的初始渲染和运行时间
- 更小的包大小和更快的页面加载
- 更易读的堆栈跟踪
- 调试更简单
在组件中使用 zoneless 的最佳方法是使用 Signals:
@Component({
...
template: `
<h1>Hello from {{ name() }}!</h1>
<button (click)="handleClick()">Go Zoneless</button>
`,
})
export class App {
protected name = signal('Angular');
handleClick() {
this.name.set('Zoneless Angular');
}
}
在上面的示例中,单击按钮会调用 handleClick 方法,该方法会更新信号值并更新 UI。这与使用 zone.js 的应用程序类似,几乎没有什么区别。通过 zone.js,Angular 可以在应用程序状态发生变化时随时运行变化检测。如果没有区域,Angular 会将这种检查限制为更少的触发器,例如信号更新。此更改还包括一个具有合并功能的新调度程序,以避免连续多次检查更改。
例如,当用户单击上面的按钮时,由于调度程序的合并,Angular 将仅运行一次更改检测。在我们的文档中了解更多zoneless 信息。
更新为 zoneless
Angular 最近经历了令人兴奋的演变,zoneless 是其中的核心部分。在发展框架的同时,我们确保所有现有的 API 继续按预期工作,并且与我们引入 Angular 的所有新功能都有良好的互操作性。
Zoneless 是我们互操作性方法的另一个例子。最重要的是,我们希望确保将现有应用程序迁移到zoneless 尽可能简单。如果您的组件与 Angular 的 ChangeDetectionStrategy.OnPush
更改检测策略兼容,那么它们也应该与 zoneless 大部分兼容,这将使它们的过渡无缝!
Coalescing by default 默认合并
从 v18 开始,我们对 zoneless 应用程序和使用启用合并的 zone.js 的应用程序使用相同的调度程序。为了减少新 zone.js 应用程序中更改检测周期的数量,我们还默认启用区域合并。此行为仅针对新应用程序启用,因为它可能会导致依赖于先前更改检测行为的应用程序出现错误。合并减少了不必要的变更检测周期,并显著提高了某些应用程序的性能。
要选择对现有项目进行事件合并,请在 bootstrapApplication
中配置您的 NgZone
提供商:
bootstrapApplication(App, {
providers: [
provideZoneChangeDetection({ eventCoalescing: true })
]
});
Zoneless 应用程序的原生 await
Zone.js 拦截许多浏览器调用以插入 Angular 的更改检测。不幸的是,async/await 是 zone.js 无法修补的 API 之一,因此我们需要通过 Angular CLI 将其降级为 Promise。这是次优的,因为所有现代浏览器都支持 async/await,它们比 Promise 更具表现力,并且由 JavaScript 运行时优化。
如今,如果您创建一个使用实验性 Zoneless 变更检测的应用程序,Angular CLI 将使用原生的 async/await,而不会将其降级为 Promise。这将改进调试并使您的包更小。
组件支持 Zoneless
我们在 Angular CDK 和 Angular Material 中启用了zoneless 支持。这也帮助我们发现并完善了zoneless 模型的一些粗糙边缘。
Angular 开发者的新家
在过去的 18 个月里,我们在 angular.dev 上努力工作,以提供直观、实用的入门之旅和改进的深入指南。今天,我们很高兴地宣布 angular.dev 是 Angular 的官方文档网站!
除了新的、现代的外观和感觉之外,您还可以找到基于 WebContainers 的交互式实践教程、带有示例的交互式游乐场、由 Algolia 支持的改进搜索、更新的指南、简化的导航等等!
Angular.dev 的主页
所有对 http://Angular.io 的请求现在都会自动重定向到 Angular.dev。为了确保所有现有链接继续有效,我们将开发人员转发到 http://v17.angular.io。去 angular.dev 看看吧!
Material 3 现已稳定!
几个月前,我们引入了对 Material 3 的实验性支持。在解决了开发人员的反馈并完善了我们的 Material 3 组件后,我们很高兴将它们升级到稳定版本!
与此同时,我们还使用新的 Material 3 主题和文档更新了http://material.angular.io。
您今天可以在我们的指南中找到如何在您的应用程序中使用 Angular Material 3!
开发者预览版中的 Signal APIs
在 Angular 17.1 和 17.2 版本中,我们宣布了新的信号 input、基于信号的查询和新的 output 语法。在我们的信号指南中了解如何使用这些 API。在接下来的几个月里,我们将根据您的反馈继续迭代改进,直到我们将其升级到稳定状态。
可延期视图现已稳定
在过去的六个月中,我们听到了很多关于可延迟视图的令人兴奋的消息,以及它们如何使开发人员能够轻松改进其应用程序的核心 Web Vitals。例如,http://Bill.com 表示,通过使用 @defer ,他们将其中一款应用程序的捆绑包大小减少了 50%。今天,可延期观点现已稳定!您可以在您的应用程序和库中使用它们。
内置控制流现已稳定
除了可延迟视图之外,在 v17 中,我们还宣布了具有改进性能的新内置控制流。我们已经看到这种新语法得到了广泛的采用,在解决了社区反馈之后,我们很高兴地宣布这个 API 是稳定的!在预览期间,我们进一步改进了控制流的类型检查,启用了更符合人体工程学的隐式变量别名,并为某些与性能相关的反模式设置了护栏。
服务器端渲染的改进
大约一年前,我们引入了水合功能,并在 v17 中将其升级为稳定版本。根据公共 HTTPArchive 数据集,76% 使用预渲染或服务器端渲染的 Angular v17 应用程序已经在使用水合作用。要让更多人利用水合作用,有一个主要障碍——缺乏国际化支持。与 Chrome Aurora 团队合作后,我们很高兴与大家分享,i18n 块的水合作用在 v18 的开发者预览模式中可用!
事件回放
不到两个月前,我们宣布了一个长期正在进行的项目,旨在融合 Angular 和 Google 内部框架 Wiz。提醒一下,Angular 和 Wiz 过去一直服务于两个不同的应用程序领域——Wiz 主要用于以消费者为中心的应用程序,高度关注性能,而 Angular 则专注于生产力和开发人员体验。作为融合努力的结果,Wiz 将 Angular Signals 深度集成到其渲染模型中。在 ng-conf 上,我们分享了 YouTube 现在如何使用 Angular Signals。同样,Angular 现在带来了越来越多以性能为中心的功能,例如部分水合,我将在稍后分享更多内容。
在这两种情况下,我们都会使用您的功能请求和其他要求作为融合两个框架的基本功能的动力。
今天,我们很高兴与大家分享,http://Google.com 上运行的核心库之一——事件调度(以前称为 jsaction)现在已位于 Angular monorepo 中。从 v18 开始,事件调度在使用混合渲染时支持事件重放。大多数开发人员不会直接与事件调度交互,因此让我们研究一下为什么事件重播很有用。您可以在下面找到一个简单的电子商务网站的模拟。我们引入了人工加载延迟来模拟非常慢的网络连接。想象一下,当页面正在加载且尚未水合时,用户想要将多个耳机添加到购物车中。如果页面尚未水合,因此不具有交互性,则所有用户事件都将丢失。从 v18 开始,使用事件调度,Angular 将开始记录用户事件。一旦应用程序被水合,事件调度就会重播它们,我们最终会在购物车中看到六件商品。
在 Angular 中使用事件调度来重放事件
事件重播功能在 v18 开发者预览版中提供。您可以使用 withEventReplay()
启用它,例如:
bootstrapApplication(App, {
providers: [
provideClientHydration(withEventReplay())
]
});
改进的调试体验
我们更新了 Angular DevTools 以可视化 Angular 的水合过程。在每个组件旁边,您可以找到一个代表组件水合状态的图标。要预览页面上 Angular 水合的组件,您还可以启用叠加模式。如果您的应用程序存在任何水合错误,Angular DevTools 会在组件资源管理器中将其可视化。
Angular DevTools 水合调试
非常感谢我们的社区贡献者 Matthieu Riegler 添加此功能!
CDK 和 Material 中的水合作用支持
在 v17 中,一些 Angular Material 和 CDK 组件选择退出水合作用,这导致了它们的重新渲染。从 v18 开始,所有组件和基础功能都完全水合兼容。
我们的部分 Hydration 计划
我们在 ng-conf 和 Google I/O 上宣布了部分水合。这是一种允许您在服务器端渲染后逐步补充应用程序的技术。应用程序的增量水合可以预先加载更少的 JavaScript,并提高应用程序的性能。
部分水合与可延迟视图建立在相同的基础之上。您将能够启用一种模式,让 Angular 在服务器上渲染 @defer 块的主要内容,而不是像今天那样在服务器上渲染 @placeholder 块。在客户端,仅当满足模板中指定的触发条件时,Angular 才会下载关联的 JavaScript 并水合延迟块。例如,这是一个假设的 API:
@defer (render on server; on viewport) {
<app-calendar/>
}
上面的块将在服务器上呈现日历组件。一旦到达客户端,Angular 将下载相应的 JavaScript 并水合日历,使其仅在进入视口后才具有交互性。我们一直在积极设计部分水合的原型,并且我们正处于一种可以与交互触发器一起使用的状态。我们目前正在与合作伙伴合作评估数据触发器的重要性,例如传递接收属性或更改绑定值的组件。
如果您正在大规模构建性能关键型应用程序,并且希望加入我们的抢先体验计划来塑造部分水合的未来,请发送电子邮件至 devrel@angular.io。
使用 Firebase 应用托管为您的应用提供强大的托管
随着 Web 平台的复杂性不断增加,应用程序的托管在性能、可靠性、生产力和规模方面发挥着至关重要的作用。使用混合渲染的应用程序对服务器端渲染、预渲染和客户端渲染有不同的托管要求。手动管理这种复杂性可能会很麻烦。Firebase App Hosting 现在可以为开发人员透明地处理所这些!
Firebase 在今年的 Google I/O 上宣布了应用托管。应用托管简化了动态 Angular 应用程序的开发和部署,提供内置框架支持、GitHub 集成以及与其他 Firebase 产品(如身份验证、Cloud Firestore 和 Vertex AI for Firebase)的集成。我们已经与 Firebase 合作了一年多的时间,以确保 Angular 的开发者获得流畅的体验。立即查看他们的快速入门,开始使用应用程序托管!
还有更多……
除了我们正在推进的大型计划之外,我们始终花时间解决常见的开发人员需求。以下是 v18 的一些亮点:
为 ng-content 指定默认内容
我们遇到的投票最多的问题之一是为 ng-content 指定默认内容。v18 现已可用!这是一个简单的例子:
@Component({
selector: 'app-profile',
template: `
<ng-content select=".greeting">Hello </ng-content>
<ng-content>Unknown user</ng-content>
`,
})
export class Profile {}
现在我们可以使用该组件:
<app-profile>
<span class="greeting">Good morning </span>
</app-profile>
这将导致:
<span class="greeting">Good morning </span>
Unknown user
统一控制状态变化事件
Angular 表单中的 FormControl
、 FormGroup
和 FormArray
类现在公开一个名为 events
的属性,它允许您订阅事件流对于这个表单控件。使用它您可以跟踪值、触摸状态、原始状态和控制状态的变化。
现在您可以使用:
const nameControl = new FormControl<string|null>('name', Validators.required);
nameControl.events.subscribe(event => {
// process the individual events
});
此功能请求在 GitHub 上获得了超过 440 个赞。感谢我们的社区贡献者 Matthieu Riegler 将其提供给所有人!
自动迁移到应用程序构建器
在 Angular v17 中,我们宣布“应用程序构建器”稳定,并默认为新项目启用它。在底层,它使用 Vite 和 esbuild 来取代以前的 webpack 体验。对于大多数应用程序,开发人员能够通过更新其 angular.json 来更新到新的构建系统。在过去的 6 个月中,我们从人们那里收集了更多反馈并完善了更新体验,以使每个人都能转向新的构建体验并获得编辑/刷新的提升。
您可以在我们的更新指南中找到我们开发的用于自动化您的更新体验的工具。
由于 webpack 不在新构建系统的关键路径上,因此我们将对 webpack 的依赖设置为可选,这使我们能够将 Angular CLI 的依赖项总数减少 50% 以上!此更改将加快 Angular CLI 安装时间。
路由重定向作为函数
为了在处理重定向时实现更高的灵活性,在 Angular v18 中,redirectTo 现在接受一个返回字符串的函数。例如,如果您想重定向到依赖于某些运行时状态的路由,您可以在函数中实现更复杂的逻辑:
const routes: Routes = [
{ path: "first-component", component: FirstComponent },
{
path: "old-user-page",
redirectTo: ({ queryParams }) => {
const errorHandler = inject(ErrorHandler);
const userIdParam = queryParams['userId'];
if (userIdParam !== undefined) {
return `/user/${userIdParam}`;
} else {
errorHandler.handleError(new Error('Attempted navigation to user page without user ID.'));
return `/not-found`;
}
},
},
{ path: "user/:userId", component: OtherComponent },
];
TypeScript 5.4
最后但并非最不重要的一点是,我们更新了对 TypeScript 的依赖关系,让您可以利用所有最新的 TypeScript 5.4 功能!
社区亮点
随着 Angular 的创新,我们也看到了社区的大量进步!
ngrx、ngxs 和 rxAngular 等流行的状态管理库已经采用 Angular 信号并在组件中实现细粒度的反应性。
两个月前,Angular GDE Brandon Roberts 发布了 Analog.js 的 1.0 版——一个社区驱动的 Angular 元框架。它提供了一些简洁的功能,例如基于文件的路由、API 路由、一流的 Markdown 支持等等。Analog.js 团队一直在尝试社区一直喜爱的单文件组件格式!看到来自其他生态系统的流行库构建他们的 Angular 适配器也令人兴奋。Chau Tran、Arnoud de Vries 和 Corbin Crutchley 为 Angular 提供了 TanStack Store、TanStack Query 和 TanStack Forms 支持!
我们也很高兴能够参加世界各地如此多的 Angular 社区会议,并期待今年晚些时候会发生什么。组织一场有数百名与会者和数十名演讲者的会议并不是一件容易的事,向今年成功实现这一艰巨任务的所有人大声喊叫,包括 ng-conf、Angular Belgrade、ng-de、ng-be、NGPoland、 ngRome、NG 肯尼亚、ngIndia、Angular TLV!如果我们错过了任何会议,请在评论中分享。
除此之外,自 v16 以来,我们还收到了超过 290 人的贡献!感谢所有通过代码、问题、内容、组织社区或以他们认为可能的方式帮助使 Angular 变得更好的人
反思我们的进步
作为 Angular 复兴的一部分,我们在过去两年中交付了很多成果,并且还会有更多创新。在本节中,我想借此机会回顾一下现在并庆祝我们所处的位置。
在将 Angular 发展为具有信号的真正反应式框架并引入先进的混合渲染功能的同时,我们始终恪守我们的使命,让开发人员能够充满信心地交付 Web 应用程序。全球第二大网站 YouTube 使用 Angular 的反应原语,我们正在作为一个更大的工作组的一部分进行合作,将 Signals 添加到网络平台。
我们还与 Vite、Nx、Cypress、Puppeteer、Storybook 等工具的作者密切合作,以改善每个人的开发者体验。与此同时,我们非常幸运地拥有一个由充满热情的开发人员、社区组织者、作者和演讲者组成的社区,他们不断突破 Angular 的可能性界限。
感谢大家参与 Angular 复兴!