Angular Tree Shaking:它究竟是如何工作的?

Cod*_*n25 11 typescript angular-cli tree-shaking angular angular8

我们目前正在尝试优化复杂的 Angular 应用程序(性能和包大小)。

我们发现我们有部分未使用的组件,但我们不能 100% 确定它们。无论如何......我们目前要问的问题是在 Angular 中摇树究竟是如何工作的。

问题 1)如果在模块的声明、导入或提供者数组中有条目,但该模块没有在任何地方使用,它们是否也通过摇树移除或包含在最终包中?

例子:

@NgModule({
  imports: [
    FirstModule,
    SecondModule  // Is not used anymore (probably) but imported here
  ],
  declarations: [SampleComponent] // Is not used anymore (probably) but imported here
})
export class SampleModule {
}
Run Code Online (Sandbox Code Playgroud)

信息:该模块/组件的路由已被删除。

问题 2)仅从路由模块中移除这些组件是否足以使摇树过程成功?

问题 3)要使摇树过程达到最佳状态,应该具备哪些条件?

使用 Angular 8.2 版

Kev*_*eal 10

关于摇树在 Angular 中的工作原理

摇树主要在缩小阶段完成,并不特定于 Angular。terser是他们在 Angular CLI 中使用的压缩器,它是支持 ES6 语法的 Uglify 的一个分支。

terser 读取您的代码,如果它没有在其他地方引用,并且可以肯定删除某些代码不会产生副作用,那么它将删除该代码。

terser不能确定带有装饰器的类在定义时是否有副作用(装饰器是函数调用)。在 Angular 的生产版本中,他们有一个名为“build-optimizer”的 webpack 插件,它会去使用他们的装饰器的地方,并/*@__PURE__*/在编译的 javascript(来自 Typescript)旁边添加一个特殊的注释,它terser识别并删除装饰类(如果它是其他地方未提及)。

关于从 NgModule 中移除组件

构建过程只是从您的main.ts文件开始,并抓取所有文件的所有导入以包含在您的构建中。如果从 main.ts 文件中,您的组件文件从未被爬行过程找到的任何文件导入,则它将永远不会被包含在内。这不是摇树,它根本没有包含在构建过​​程中。

如果您的模块文件是唯一导入组件文件的地方,那么删除该导入就足以不将该组件包含在您的构建中。

关于你可以做的事情

您可以进行一些特定于 Angular 的更改,以确保您只构建您使用的代码。

  1. 使用{providedIn: root}装饰选项Injectable并删除任何可注入服务、保护的地方,无论来自任何 Angular 装饰的providers: [].
  2. 使用 Ivy 渲染器,这意味着捆绑的框架更少(如果您不使用它)。

此外,在调用站点(不是定义),您可以使用/@__PURE__/注释标记任何没有副作用的函数,这样即使在某处调用它们,如果返回值可以通过其他一些优化删除,函数本身也可以移除。我还没有测试过这个,但理论上它应该可以工作。

我不知道所有不同的构建阶段如何转换您的代码,以及它们是否在terser可以看到它们之前移动或删除注释。

您可以使用此 Playground 工具对其进行测试:https : //terser-playground.surge.sh/

用这个例子试试:

(function() {
  const a = 1;
  const b = 2;
  const c = /*@__PURE__*/ test();
  console.log(a + b);
}());

function test() {
  return 3
}
Run Code Online (Sandbox Code Playgroud)


Fah*_*heb 6

您可以使用webpack-bundle-analyzer,它可以帮助您在最终输出文件中可视化大小和不同使用的组件。这样您就可以确定是否使用了模块,然后您可以安全地删除它。

  • @KevinBeal npm install -D webpack-bundle-analyzer;要使用分析数据进行构建:将 --stats-json 添加到您的 ng 构建命令中。要查看生成的分析: webpack-bundle-analyzer <path-to-stats-json> (2认同)