当前位置: 首页>后端>正文

将Nx项目升级到Angular 17

如果你正在 NX workspace 中使用Angular,并且迫不及待地想尝试最新的 Angular 功能,那么这篇文章适合你。

New features新功能

您可能已经熟悉 Angular 17 以及它带来了什么。除了新徽标和令人印象深刻的新文档页面(angular.dev)之外,它还提供了一些很棒的新功能:

  • New control flow syntax (@if, @else, etc.) 新的控制流语法(@if、@else等)
  • Faster builds with ESBuild 使用 ESBuild 加快构建速度
  • Deferrable views可延迟视图
  • Enhanced SSR support增强的 SSR 支持

新的控制流和更快的构建从根本上改善了开发人员体验,为尽快更新项目提供了强大的动力。

升级步骤

本文介绍了一个示例更新过程,包括特定于项目的详细信息和潜在挑战。但是,在您自己的项目中,使用您独特的设置,您可能会遇到不同的障碍。

在 NX 工作区中,更新过程应与执行以下命令一样简单:

// Updates your dependencies in package.json
// and generates a migrations.json file
npx nx migrate latest

// Installs the new dependencies
npm install

// Executes the migration scripts based on migrations.json one-by-one
npx nx migrate --run-migrations</pre>

从理论上讲,这听起来很简单。在实践中,经常会出现问题。

Migrate latest命令的作用

在继续之前,让我们先看看有什么 npx nx migrate latest 作用。

此命令将 package.json 文件中的所有 @nx/* 和 @angular/* 依赖项更新到最新版本。我发现的值得注意的例外是 @angular/cli,它在迁移过程中稍后进行了更新。

此外,它还会生成一个 migrations.json 文件,其中包含应在代码上执行的所有脚本以采用更改 - 例如。自动配置更改等。

Npm install 的问题

剧透: npm install --force 解决了循环依赖项问题,该问题在以后的全新安装期间不会导致任何问题 ( npm ci )。

细节:在一些场景下, npm install 失败并出现此错误:

npm ERR! While resolving: ev-portals@0.0.0
npm ERR! Found: @angular-devkit/build-angular@16.2.1
npm ERR! node_modules/@angular-devkit/build-angular
npm ERR! dev @angular-devkit/build-angular@"17.0.0" from the root project
npm ERR! peer @angular-devkit/build-angular@">= 14.0.0 < 17.0.0" from @nx/angular@16.8.1
npm ERR! node_modules/@nx/angular
npm ERR! @nx/angular@"17.1.1" from the root project
npm ERR! @nx/angular@"16.8.1" from @nrwl/angular@16.8.1
npm ERR! node_modules/@nrwl/angular
npm ERR! @nrwl/angular@"16.8.1" from @nx/angular@16.8.1
npm ERR! 2 more (@storybook/angular, jest-preset-angular)</pre>

这意味着,我的 @nx/angular@16.8.1 包仍然希望使用比现在在 package.json 文件 (17.0.0) 中定义的版本更早的 @angular-devkit/build-angular。奇怪的是,我的package.json在更新后已经包含@nx/angular@17.1.1......因此,首先我尝试只安装这个包,因此它优先。

npm i @nx/angular@17.1.1

它再次失败了,报错:

npm ERR! peer @angular-devkit/build-angular@">=14.1.0 < 17.0.0" from @storybook/angular@7.0.18

虽然我在package.json文件中已经有@storybook/angular@7.5.3...所以我继续这个单独的安装。

npm i @storybook/angular@7.5.3

这次的结果是

npm ERR! While resolving: ev-portals@0.0.0
npm ERR! Found: @angular-devkit/build-angular@16.2.1
npm ERR! node_modules/@angular-devkit/build-angular
npm ERR! peer @angular-devkit/build-angular@">= 14.0.0 < 17.0.0" from @nx/angular@16.8.1
npm ERR! node_modules/@nx/angular
npm ERR! @nx/angular@"16.8.1" from @nrwl/angular@16.8.1
npm ERR! node_modules/@nrwl/angular
npm ERR! @nrwl/angular@"16.8.1" from @nx/angular@16.8.1
npm ERR! @nx/angular@"17.1.1" from the root project
npm ERR! peer @angular-devkit/build-angular@">=14.1.0 < 17.0.0" from @storybook/angular@7.0.18
npm ERR! node_modules/@storybook/angular
npm ERR! dev @storybook/angular@"7.5.3" from the root project
npm ERR! 2 more (jest-preset-angular, the root project)</pre>

似乎我们回到了根目录,@nx/angular 包又来了,我们只是尝试单独安装。.在这一点上,由于我找不到单个软件包安装的正确组合或顺序,我选择了 --force install,然后,我检查了全新安装,一切按预期工作。

运行升级命令

在执行时值得注意控制台输出,因为它提供了正在执行 npx nx migrate --run-migrations 的内容的分步详细信息。

Ran 17.0.0-move-cache-directory from nx
Updates the default cache directory to .nx/cache

UPDATE .gitignore
UPDATE .prettierignore

Ran 17.0.0-use-minimal-config-for-tasks-runner-options from nx
Use minimal config for tasksRunnerOptions

UPDATE package.json
UPDATE nx.json

[object Object]
Ran rm-default-collection-npm-scope from nx
Migration for v17.0.0-rc.1

UPDATE nx.json

Ran move-options-to-target-defaults from @nx/jest
Move jest executor options to nx.json targetDefaults

UPDATE nx.json
UPDATE apps/sample-app/project.json
// Same repeats for all projects

Ran update-angular-cli-version-17-0-0 from @nx/angular
Update the @angular/cli package version to ~17.0.0.

UPDATE package.json

Ran rename-browser-target-to-build-target from @nx/angular
Rename 'browserTarget' to 'buildTarget'.

UPDATE apps/sample-app/project.json
// Same repeats for all apps

Ran update-17-0-0-rename-to-eslint from @nx/linter
update-17-0-0-rename-to-eslint

UPDATE package.json
UPDATE apps/sample-app/project.json
// Same repeats for all projects
UPDATE migrations.json

Ran block-template-entities from @angular/core
Angular v17 introduces a new control flow syntax that uses the @ and } characters. This migration replaces the existing usages with their corresponding HTML entities.

UPDATE libs/../../x.component.html
// Plus all other templates, where we had the '@' sign gets encoded to '@'

Skipping migration for project sample-project. Unable to determine 'tsconfig.json' file in workspace config.

// Same repeats for all projects (apps and libs)

  ?  Updated Angular Material to version 17

Skipping migration for project sample-project. Unable to determine 'tsconfig.json' file in workspace config.

// Same repeats for all projects (apps and libs)

总而言之,在根文件夹中引入了一个新的 .nx 缓存文件夹,更新了 @angular/cli,@ 和 { 字符在模板中被替换为它们的 HTML 实体——由于新的控制流语法——并且执行了一堆 nx.json 和 project.json 配置更改,例如将 @nx/linter:eslint 重命名为 @nx/eslint:lint。

好的,太好了,我们成功地更新了项目,或者,不是吗?当我尝试验证项目(通过linting,构建,测试)时,它抛出了以下错误:

Unable to resolve @nrwl/linter:eslint

这是某些project.json文件中的lint执行程序,似乎在某些项目中它没有被替换到较新版本,因此我不得不手动更新这些project.json文件:

"lint": {
"executor": "@nx/eslint:lint",
...

在运行linting期间,可能会发生一些以前没有的错误,即:

@typescript-eslint/no-unused-vars

error 'x' is defined but never used @typescript-eslint/no-unused-vars

and @typescript-eslint/no-explicit-any 和 @typescript-eslint/no-explicit-any

error Unexpected any. Specify a different type @typescript-eslint/no-explicit-any

不完善的快速解决方法是将错误切换为警告 - 就像它们最初一样 - 只需更改您的全局 eslint 配置:

{
"files": [".ts", ".tsx"],
"extends": ["plugin:@nx/typescript"],
"rules": {
"@typescript-eslint/no-explicit-any": "warn",
"@typescript-eslint/no-unused-vars": "warn",
...

所以现在我们可以说,我们迁移到了最新版本的 @nx 并成功@angular。尽管我们仍然有旧的 ngFor、ngIf 等控制流程,因为到目前为止,nx 没有提供自动更新迁移脚本。

采用Angular17 新的控制流语法

幸运的是,@angular/core 在这里提供了支持。只需在 NX 工作区的根文件夹中运行 ng g @angular/core:control-flow 即可。请注意,此脚本处于开发者预览阶段,因此请谨慎使用。

ng g @angular/core:control-flow

在我们应用自动更新并执行测试后,我们收到了一条新的错误信息:

@switch block can only contain @case and @default blocks

事实证明,我们在 中使用了 if 中的语句,但没有在 case 中使用 switch .这相对容易解决,只需将 if 语句移出 switch .

后来,我们注意到,模板的格式不像以前那么漂亮,所有更新的文件中都缺少正确的缩进。

如果您使用的是 prettier,最简单的解决方案是在模板上运行它:

npx prettier ./*/.html --write

当然,您可以根据需要随意更改通配符 ./**/*.html 路径。在你这样做之前,你可能还想更新到 prettier@3.1.0,因为它增加了对 Angular 新控制流语法的额外支持

npm i prettier@3.1.0 --save-dev

注意:我还必须重新启动我的 VSCode,否则新版本的 prettier 无法在编辑器中开始工作。

运行prettier仍然会遇到所谓的 ICU 表达式(由 angular i18n 支持)上的错误

SyntaxError: Unexpected closing block. The block may have been closed earlier. If you meant to write the } character

在这里,您可以决定等待更漂亮的修复程序,或者通过计算代码中的正确字符串来替换它们。

采用新的基于 ESBuild 的构建器

好的,到目前为止很棒,但不要止步于此。Angular 17 还为我们带来了一个伟大的新构建器,它比以往任何时候都更快——这要归功于 esbuild。

为了更好地了解发生了什么变化以及具体变化如何,值得一看 Angular 文档页面。

简而言之,您有两种选择,要么使用

  • **browser builder ** — 更易于采用
  • **application builder **— 更健壮

如果您使用浏览器构建器,您唯一需要更改的是相应 project.json 文件中的构建器名称

@angular-devkit/build-angular:browser

改为

@angular-devkit/build-angular:browser-esbuild

所以我们添加了一个 -esbuild 后缀,8 个字母,我们有一个更快的构建,很划算,对吧?

不过,推荐的方法是使用应用程序构建器,它可以让您更好地为未来做好准备,例如通过提供 SSR 或 SSG 功能。

在这种情况下,您必须在 @angular-devkit/build-angular:applicationangular.json中使用,您必须将选项重命名为 browser ,并删除一堆不再相关的 main 选项:buildOptimizer,resourcesOutputPath,vendorChunk,commonChunk,deployUrl,ngswConfigPath

就是这样,也不是那么疯狂。

还要注意,随着新版本的推出,您所拥有的一切都 dist/apps/x 将移动到 dist/apps/x/browser.

回顾

也许从以前版本的 nx 和 angular 升级到 v17 比简单地运行 1-2 个命令要多一些努力,但这绝对是值得的。

Angular Renaissance 正处于最佳状态,新功能极大地改善了 DX,所以不要犹豫,试试吧!


https://www.xamrdz.com/backend/3nz1943672.html

相关文章: