Angular 15 更新后的 Typescript 目标警告

Kon*_*rad 30 typescript angular angular14 angular15

我将我的 Angular 应用程序更新到 Angular 15。它构建正常 - 除非出现一些警告,例如:

TypeScript 编译器选项“target”和“useDefineForClassFields”分别由 Angular CLI 设置为“ES2022”和“false”。

我的tsconfig.json目标是ES6

{
  ...
  "compilerOptions": {
      "target": "ES6",
      ...
  }
}
Run Code Online (Sandbox Code Playgroud)

文档说:

在内部,Angular CLI 现在始终将 TypeScript 目标设置为 ES2022,并将 useDefineForClassFields 设置为 false,除非在 TypeScript 配置中将目标设置为 ES2022 或更高版本。

https://github.com/angular/angular-cli/blob/main/CHANGELOG.md

我的 .browserslistrc 看起来一个月都没有变化,从一开始就没有变化:

last 1 Chrome version
last 1 Firefox version
last 2 Edge major versions
last 2 Safari major versions
last 2 iOS major versions
Firefox ESR
Run Code Online (Sandbox Code Playgroud)

那么,我怎样才能摆脱这个警告呢?

JSO*_*ulo 34

要理解此警告,我们首先需要了解 Angular 构建的工作原理。

首先,需要运行 TypeScript 构建。在此步骤中,根据 中的设置tsconfig.json,您的 TypeScript 代码将被编译为 JavaScript。如果设置targetES6,在 Angular 15 之前,TypeScript 构建将生成 ES6 代码。

之后,Angular 使用Babel使生成的 JavaScript 代码向后兼容旧的浏览器版本,请参阅文档。它通过 browserslist 配置来获取您希望支持的浏览器列表,并在必要时为缺少的功能添加填充。

在 Angular 支持 IE11 的时代,这要复杂得多。有一次,Angular CLI 甚至专门为 IE11 生成了一个额外的包,这称为差异加载。但现在 Angular 放弃了对 IE11 的支持,他们可以再次简化事情并转向现代捆绑包,这可能是他们在 v15 中进行更改的原因。

所以在我看来,没有充分的理由将target你的设置tsconfig.json为像这样的旧版本ES6。现代浏览器现在支持更多的 EcmaScript 功能,并且使用更新的 EcmaScript 版本将使您的包大小更小。无论如何,Babel 都会填补缺失的功能,所以你不必担心。只需像他们建议的那样将目标设置为 ES2022 即可。

  • 谢谢,但“正式”支持 14 和通过使用较低的“目标”(或更宽松的浏览器文件)能够支持 14 之间是有区别的。这正是我昨天一直在做的事情,以支持旧版 Safari 中的“??”和“?.” - 我们仍然从 Safari 13 和 14 人身上赚钱!只是很难了解应用程序中每个选项的确切影响,但我个人认为自己暂时不会使用 ES2022。 (3认同)

use*_*108 16

我遇到了同样的问题,并通过将"target": "ES2022"和 添加"useDefineForClassFields": false到我的tsconfig. 这是否是一个好主意,必须等待比我更有知识的人发表评论。我担心这会像你现在的2022情况一样失败2023(或者接下来发生的任何事情)。如果 Angular 无论如何都会覆盖它,那么如果它可以完全被忽略(就像我所做的那样),当然会更好。但我对这个问题的理解可能不完全。

就您而言,您应该能够做(或至少尝试)相同的事情来代替ES6(我理解与相同ES2015)。根据您引用的文档,无论您的请求如何,这都是 Angular 正在做的事情,所以如果您只收到警告并且没有错误,您的代码应该没问题。如果您需要将事情进一步限制到 ES6 级别,似乎您需要使用您的.broswerslistrc文件来执行此操作,这可能也已经很好了。

我认为这里的问题是这个警告没有帮助,至少对像你我这样的人来说是这样,他们收到警告却不知道该怎么办。此外,它后面的网络链接(“要控制 ECMA 版本和功能,请使用 Browerslist 配置。有关更多信息,请参阅https://angular.io/guide/build#configuring-browser-compatibility ”)在以下方面似乎没有特别帮助:解决警告,告诉我们应该做什么,但不告诉我们如何消除警告。


Sim*_*ver 10

编辑:事实证明存在与此警告相关的错误,已在 Angular CLI 16.0.4 中修复。对于 Angular CLI 15 - 16.0.3,请确保进行设置target="ES2022"以避免出现下述不匹配情况。使用 检查您的 CLI 版本ng version


请小心不要误解该警告及其后果!

完整的消息(从 Angular 16 开始)是这样说的:

TypeScript 编译器选项“target”和“useDefineForClassFields”分别由 Angular CLI 设置为“ES2022”和“false”。要控制 ECMA 版本和功能,请使用 Browerslist 配置。有关更多信息,请参阅https://angular.io/guide/build#configuring-browser-compatibility 注意:您可以在项目的 tsconfig 中将“target”设置为“ES2022”以删除此警告。

对此的一种相当合理的解释可能是:

Angular忽略了compilerOptions.target我在你的 中添加的任何内容tsconfig.json,并将我的代码编译为 ES2022。

然而,事实并非如此!

为了确认这一点,我ng new使用 Angular 16 创建了一个简单的项目,并将目标更新为 ES2015:

compilerOptions: {
   "target": "ES2015"
}
Run Code Online (Sandbox Code Playgroud)

我在 AppComponent 中编写了以下几行代码,使用了ES2022 的一项功能nullish 合并运算符。

const cat = null;
const dog = { catName: 'Kim' };

const animal = cat ?? dog;
Run Code Online (Sandbox Code Playgroud)

通过查看在浏览器中运行的 .js 编译代码(不是源映射的 .ts 文件),ng serve您将看到以下内容 - 证明该代码??已经被转译为与旧版浏览器兼容:

 const animal = cat !== null && cat !== void 0 ? cat : dog;
Run Code Online (Sandbox Code Playgroud)

当然,对于 ES2022 目标来说,这不会发生开箱即用的情况。

因此,假设您确实需要支持 Safari 13.0(它不支持??)并认为一切都很好。

又错了!

在浏览器中搜索,您将看到在vendor.js 文件中使用的??许多地方。??它不会在那里进行转译,因此您的应用程序无法在 Safari 13.0 上运行。

这就是 browserslist 的用武之地,如果对其进行配置,它将针对特定目标转换整个应用程序。


该消息在实践中的真正含义:

您的应用程序代码正在针对早于 ES2022 的目标进行编译,这可能会导致您的代码与供应商代码之间不匹配。我们建议将您的目标设置为 ES2022 并专门使用 browserslist 来控制旧版浏览器的转译,以确保所有代码都按预期转译。


为什么我还是很困惑:

以下引入此功能的提交似乎将目标设置为 ES2022,但它实际上从未对应用程序代码生效。不知道为什么。

https://github.com/angular/angular-cli/pull/23936/commits/cdac700b93d5593ce92b44b1691941673eaf25b0#diff-2d55449c69797885b38f6b957a1fd03d27beda366a9270293719ec041cf15d0 f