将 Angular 应用从 Webpack 构建工具迁移至 @angular/build
逐步指南:用基于 esbuild 的应用构建工具替换 Angular 的 Webpack 浏览器构建工具,同时解决输出路径、SSR、加载器以及 tsconfig 类型相关的问题。
来源: Webpack is Officially Deprecated in Angular 22: The TSGo Migration
多年来,Angular项目都是通过Webpack和@angular-devkit/build-angular来构建的。如今,CLI的默认构建工具已变为基于esbuild的@angular/build中的application构建器,而基于Webpack的构建工具则正在被淘汰:根据撰写本文时发布的Angular 22版本说明,基于Webpack的构建器已被正式废弃。以下步骤将展示如何将现有应用迁移到新的构建工具,angular.json中需要做哪些修改,如何处理自定义的Webpack加载器,以及如何为原生Go编译器准备TypeScript配置。
为何现在必须进行迁移
除了淘汰旧版本的原因外,还有性能方面的考量。在撰写本文时,基于 Go 语言开发的 TypeScript 编译器 TSGo(又称 Project Corsa)已处于发布候选阶段,据宣传其速度比基于 JavaScript 的编译器快多达 10 倍。Angular 的发展路线图旨在进一步优化该编译器,相关工具开发资源也投入到了 esbuild 和 Vite 工具链中,而非 Webpack。使用 Webpack 的项目将无法享受到这些优势。请密切关注相关时间节点,并查看最新公告。
新的构建工具还简化了目标结构。Webpack 需要为浏览器版本包、服务器版本包以及预渲染分别设置不同的构建工具;而 application 构建工具则能从单一目标生成所有这些版本包。
第一步:在 angular.json 中更换构建工具
打开 angular.json,找到项目的 build 目标,然后定位到旧的浏览器构建工具:
// DELETE the legacy Webpack builder
"build": {
"builder": "@angular-devkit/build-angular:browser",
"options": { ... }
}
将构建工具名称替换为统一的应用程序构建工具,暂时保留选项对象:
// MIGRATE to the unified esbuild application builder
"build": {
"builder": "@angular/build:application",
"options": { ... }
}
较新版本的 CLI 还提供了通过 ng update 实现的自动迁移功能,该功能会完成上述操作以及后续的选项更改;请查阅 Angular 文档以获取对应版本的准确命令,然后查看其生成的差异对比。
步骤 2:调整构建选项
application 构建工具会对选项进行更严格的验证,因此 build.options 中的若干条目需要特别留意。
- 将
main重命名为browser。 现在客户端入口点已配置为使用browser选项,main已不再被接受。 - 确定输出结构。 如果使用类似
"outputPath": "dist/app"的纯字符串,构建工具会在其中创建browser和server两个子目录。那些期望文件直接存放在dist/app中的部署脚本将会失效。若要保持客户端输出为扁平结构,应使用对象形式并将browser设置为空字符串:
"outputPath": { "base": "dist/app", "browser": "" }
- 将SSR集成到同一目标中。如果应用使用服务器端渲染,可删除独立的
server架构目标,将服务器入口点移至应用构建器的选项中,从而根据需要在那里进行预渲染:
"server": "src/main.server.ts", "prerender": true
接着运行生产环境构建,并将输出结果与服务器或CDN的预期进行比对。
步骤3:替换自定义Webpack加载器
使用@angular-builders/custom-webpack扩展构建流程的项目受影响最严重:任何自定义加载器,比如原始SVG导入或Markdown转换工具,在Webpack离开处理链后就会停止工作。有两种解决方案:
- 如SVG之类的资源:应依赖Angular内置的
assets配置,或通过CSS引用它们,而非通过加载器导入。
@angular-builders/custom-esbuild 进行注册。首先列出这些自定义配置;它们通常需要最多的开发时间。
第 4 步:为 TypeScript 7 准备 tsconfig
Angular 22 仍支持 TypeScript 5.x 和 6.x,因此目前还不需要 TSGo。不过它确实改变了某些默认设置,这些变化可能会影响类型检查。最明显的变化是 types:其默认值为空数组,因此 @types/node 或 @types/jest 等包中的全局类型声明不会再被自动识别。这样一来,process、describe 或 expect 等全局变量就会引发“找不到名称”的错误。
解决办法是明确列出每个项目所需的类型包:
// tsconfig.json
"compilerOptions": {
// You must now explicitly declare ambient types for TSGo compatibility
"types": ["node", "jest"]
}
在 tsconfig 中进行相应设置:应用代码通常比测试代码需要的全局变量更少,若在应用配置中列出 jest,则会导致测试用的全局变量泄露到生产环境类型中。
迁移检查清单
- 在
angular.json中将@angular-devkit/build-angular:browser替换为@angular/build:application。 - 将
main重命名为browser,选择合适的outputPath布局,并将 SSR 设置合并到单一目标中。 - 将自定义的 Webpack 加载器转换为资产配置或 esbuild 插件。
- 当不再有代码引用它们时,从
package.json中移除@ngtools/webpack及其他仅适用于 Webpack 的构建依赖。 - 在 TypeScript 7 之前,需在每个 tsconfig 中明确声明环境
types。
构建器的更换本身只是一个小型的配置调整;真正的难点在于自定义加载器与部署路径的设置。现在进行这项工作可以摆脱对已过时流程的依赖,让项目能够及时受益于新推出的更快编译器。如需在当前工具链上创建一个全新项目,请参阅设置现代 Angular 22 项目。