今天,我们很高兴与大家分享 Angular 发展的下一个里程碑!在过去的三个版本中,我们引入了许多新功能和改进。这一次,我们专注于完善我们交付的工作,将许多新 API 升级为稳定版,解决常见的开发人员请求,并实验性地发布最理想的路线图项目之一:无区域更改检测。
此版本的亮点包括:
- 对无区域变化检测的实验性支持
- Angular.dev 现在是 Angular 开发人员的新家
- 材料 3、可延迟视图、内置控制流现在稳定并包含一系列改进
- 服务器端渲染改进,例如 i18n 水化支持、更好的调试、Angular 材质中的水化支持,以及由与 Google 搜索相同的库提供支持的事件回放。
如需直观概述,请务必查看我们发布活动中的视频:
不断发展的变化检测
从历史上看,一个名为 zone.js 的库负责触发 Angular 的更改检测。该库具有许多开发人员体验和性能缺点。几年来,我们一直在努力寻找一种不依赖 zone.js 的 Angular 使用方式,我们非常高兴能分享第一个无区域实验性 API!
从今天开始,您可以尝试 Angular 中的实验性无区域支持!添加到应用程序引导程序中:provideExperimentalZonelessChangeDetection
bootstrapApplication(App, {
providers: [
provideExperimentalZonelessChangeDetection()
]
});
添加提供程序后,从 中的 polyfill 中删除zone.js。angular.json
展望未来,无区域为开发人员打开了许多大门:
- 改进微前端的可组合性以及与其他框架的互操作性
- 更快的初始渲染和运行时
- 更小的捆绑包大小和更快的页面加载速度
- 更具可读性的堆栈跟踪
- 调试更简单
在组件中使用无区域的最佳方式是使用信号:
代码语言:javascript复制@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');
}
}
在上面的示例中,单击按钮将调用该方法,该方法将更新信号值并更新 UI。这与使用 zone.js 的应用程序类似,几乎没有区别。借助 zone.js,Angular 会在应用程序状态可能发生变化的任何时间运行更改检测。如果没有区域,Angular 会将此检查限制为更少的触发器,例如信号更新。此更改还包括一个具有合并功能的新调度程序,以避免连续多次检查更改。handleClick
例如,当用户单击上面的按钮时,由于调度程序的合并,Angular 将仅运行一次更改检测。在我们的文档中了解更多信息。
更新为无区域
Angular 最近经历了激动人心的演变,无区域是其中的核心部分。在改进框架的同时,我们确保所有现有的 API 继续按预期工作,并且我们引入 Angular 的所有新内容都有一个很好的互操作性故事。
Zoneless 是我们互操作性方法的另一个例子。最重要的是,我们希望确保将现有应用程序迁移到无区域尽可能简单。如果你的组件与 Angular 的 ChangeDetectionStrategy.OnPush
更改检测策略兼容,那么它们也应该与无区域兼容,这将使它们的过渡无缝衔接!
默认合并
从 v18 开始,我们将对无区域应用和使用启用合并的zone.js应用使用相同的调度程序。为了减少新 zone.js 应用中的更改检测周期数,我们还默认启用了区域合并。
此行为仅对新应用程序启用,因为它可能会导致依赖于以前的更改检测行为的应用中出现 bug。合并减少了不必要的更改检测周期,并显著提高了某些应用程序的性能。
要选择加入现有项目的事件合并,请在 bootstrapApplication 中配置提供程序:NgZonebootstrapApplication
bootstrapApplication(App, {
providers: [
provideZoneChangeDetection({ eventCoalescing: true })
]
});
无区域应用的本机等待
Zone.js拦截了许多浏览器调用,以插入 Angular 的更改检测。不幸的是,async/await 是zone.js无法修补的 API 之一,因此我们需要通过 Angular CLI 将其降级为 promises。这是次优的,因为所有现代浏览器都支持 async/await,它们比 promise 更具表现力,并由 JavaScript 运行时优化。
今天,如果你创建一个使用实验性无区域变化检测的应用程序,Angular CLI 将使用本机 async/await,而不会将其降级为 promises。这将改进调试并使您的捆绑包更小。
组件支持无区域
我们在 Angular CDK 和 Angular 材质中启用了无区域支持。这也有助于我们发现和打磨无区域模型的一些粗糙边缘。
Angular 开发人员的新家
在过去的 18 个月里,我们努力 angular.dev,以提供直观、动手的入门之旅和改进的深入指南。今天,我们很高兴地宣布,angular.dev 是 Angular 的官方文档网站!
除了全新的现代外观之外,您还可以找到基于 WebContainers 的交互式动手教程、带有示例的交互式游乐场、由 Algolia 提供支持的改进搜索、更新的指南、简化的导航等等!
Angular.dev 主页
现在,所有对 angular.io 的请求都会自动重定向到 angular.dev。为确保所有现有链接继续有效,我们将开发人员转发给 v17.angular.io。
去 angular.dev 看看吧!
材料 3 现在稳定了!
几个月前,我们引入了对 Material 3 的实验性支持。在处理了开发人员的反馈并完善了我们的 Material 3 组件后,我们很高兴将它们升级为稳定版!
与此同时,我们还用新的 Material 3 主题和文档刷新了 material.angular.io。
您可以在我们的指南中找到如何在您的应用程序中使用 Angular Material 3!
开发者预览版中的信号 API
在 Angular 版本 17.1 和 17.2 中,我们宣布了新的信号输入、基于信号的查询和新的输出语法。
在我们的信号指南中了解如何使用 API。在接下来的几个月里,我们将继续根据你的反馈对实现进行迭代,直到我们将其升级为稳定版。
可延迟的视图现在稳定
在过去的六个月里,我们听到了很多关于可延迟视图的兴奋,以及它们如何使开发人员能够毫不费力地改进其应用程序的核心 Web 指标。例如,Bill.com 分享说,通过使用,他们将一个应用程序的捆绑包大小减少了 50%。今天,可延迟的视图现在很稳定!您可以在应用程序和库中使用它们。@defer
内置控制流现在稳定
在 v17 中,除了可延迟视图外,我们还宣布了新的内置控制流,并提高了性能。我们已经看到这种新语法的大量采用,在处理了社区反馈后,我们很高兴地宣布此 API 稳定!
在预览期间,我们进一步改进了控制流的类型检查,启用了更符合人体工程学的隐式变量混叠,并为某些与性能相关的反模式设置了护栏。
服务器端呈现的改进
大约一年前,我们引入了水合作用,并在 v17 中将其升级为稳定。根据公共 HTTPArchive 数据集,使用预渲染或服务器端渲染的 Angular v17 应用程序中有 76% 已经在使用水合作用。
有一个主要的障碍是让更多的人利用水合作用——缺乏 i18n 支持。在与 Chrome Aurora 团队合作后,我们很高兴地与大家分享,i18n 块的水合作用功能在 v18 的开发者预览模式下可用!
事件回放
不到两个月前,我们宣布了一个长期正在进行的项目,旨在融合 Angular 和 Google 的内部框架 Wiz。值得一提的是,Angular 和 Wiz 过去一直服务于两个不同的应用领域——Wiz 主要用于以消费者为中心的应用,高度关注性能,而 Angular 则专注于生产力和开发者体验。
作为收敛努力的结果,Wiz 将 Angular Signals 深度集成到他们的渲染模型中。在 ng-conf 上,我们分享了 YouTube 现在如何使用 Angular Signals。同样,Angular 现在带来了越来越多的以性能为中心的功能,例如部分水合作用,我稍后会分享更多内容。
在这两种情况下,我们都使用您的功能请求和其他需求作为融合两个框架的基本功能的动机。
今天,我们很高兴地与大家分享,在 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 开始,所有组件和基元都完全兼容水合。
我们的部分补水计划
我们在 ng-conf 和 Google I/O 上宣布了部分水合作用。这是一种技术,允许您在服务器端呈现后逐步为应用补水。应用程序的增量冻结可以减少前期加载的 JavaScript,并提高应用程序的性能。
部分水合作用建立在与可延迟视图相同的基础之上。而不是像今天这样在服务器上渲染@placeholder块,您将能够启用一种模式,让 Angular 在服务器上渲染@defer块的主要内容。在客户端上,Angular 将下载关联的 JavaScript,并仅在满足模板中指定的触发条件时对延迟块进行水合。例如,下面是一个假设的 API:
代码语言:javascript复制@defer (render on server; on viewport) {
<app-calendar/>
}
上面的块将在服务器上呈现日历组件。到达客户端后,Angular 将下载相应的 JavaScript 并给日历加水,使其仅在进入视口后进行交互。
我们一直在积极地对部分水合作用进行原型设计,并且我们已经处于一种状态,即它已经可以与交互触发器一起使用。我们目前正在与合作伙伴合作,评估数据触发器的重要性,例如传递接收属性或更改绑定值的组件。
如果您正在大规模构建性能关键型应用程序,并希望加入我们的抢先体验计划以塑造部分补水的未来,请在 devrel@angular.io 上给我们发送电子邮件。
使用 Firebase App Hosting 为您的应用提供强大的托管功能
随着 Web 平台的日益复杂,应用程序的托管在性能、可靠性、生产力和规模方面起着至关重要的作用。使用混合渲染的应用对服务器端渲染、预渲染和客户端渲染有不同的托管要求。手动管理这种复杂性可能很麻烦。Firebase App Hosting 现在为开发人员透明地处理所有这些问题!
Firebase 在今年的 Google I/O 大会上宣布了 App Hosting。App Hosting 简化了动态 Angular 应用程序的开发和部署,提供内置框架支持、GitHub 集成以及与其他 Firebase 产品(如 Authentication、Cloud Firestore 和 Vertex AI for Firebase)的集成。
我们已经与 Firebase 合作了一年多,以确保开发人员使用 Angular 的流畅体验。查看他们的快速入门,立即开始使用 App Hosting!
还有更多...
除了我们正在推进的大型计划外,我们总是花时间解决常见的开发人员需求。以下是 v18 的一些亮点:
指定 ng-content 的回退内容
我们遇到的最受好评的问题之一是为 ng-content 指定默认内容。在 v18 中,它现在可用!下面是一个简单示例:
代码语言:javascript复制@Component({
selector: 'app-profile',
template: `
<ng-content select=".greeting">Hello </ng-content>
<ng-content>Unknown user</ng-content>
`,
})
export class Profile {}
现在我们可以使用组件:
代码语言:javascript复制<app-profile>
<span class="greeting">Good morning </span>
</app-profile>
这将导致:
代码语言:javascript复制<span class="greeting">Good morning </span>
Unknown user
统一控制状态更改事件
FormControl
,Angular 窗体中的类现在公开一个名为 的属性,该属性允许您订阅此窗体控件的事件流。使用它,您可以跟踪值、触摸状态、原始状态和控制状态的变化。FormGroupFormArrayevents
现在您可以使用:
代码语言:javascript复制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 现在接受返回字符串的函数。例如,如果要重定向到依赖于某些运行时状态的路由,则可以在函数中实现更复杂的逻辑:
代码语言:javascript复制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 },
];
打字稿 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 发布了 TanStack Store、TanStack Query 和 TanStack Forms 对 Angular 的支持!
我们也很高兴能参加世界各地的众多 Angular 社区会议,并期待今年晚些时候即将举行的会议。组织一场有数百名与会者和数十名演讲者的会议并非易事,请向今年设法实现这项艰巨任务的所有人大声疾呼,包括 ng-conf、Angular Belgrade、ng-de、ng-be、NGPoland、ngRome、NG Kenya、ngIndia、Angular TLV!如果我们错过了任何会议,请在评论中分享。
除此之外,自 v16 以来,我们还收到了来自 290 多人的贡献!感谢所有帮助 Angular 改进代码、问题、内容、组织社区或以他们认为可能