Angular2 CLI巨大的供应商包:如何提高prod的大小?

Bla*_*axy 118 webpack angular-cli angular

我有一个简单的应用程序,初始化angular-cli.

它显示相对于3条路线的一些页面.我有3个组件.在这个页面的一个上,我使用lodash和Angular2 Http模块来获取一些数据(使用Rxjs Observables,map和subscribe).我使用简单的ngFor显示这些元素.

但是,尽管我的应用程序非常简单,但我得到了一个巨大的(在我看来)捆绑包和地图.我没有谈论gzip版本,但在gzipping之前的大小.这个问题只是一般性的建议问题.

一些测试结果:

建立

哈希:8efac7d6208adb8641c1时间:10129ms chunk {0} main.bundle.js,main.bundle.map(main)18.7 kB {3} [initial] [rendered]

chunk {1} styles.bundle.css,styles.bundle.map,styles.bundle.map(styles)155 kB {4} [initial] [rendered]

chunk {2} scripts.bundle.js,scripts.bundle.map(scripts)128 kB {4} [initial] [rendered]

chunk {3} vendor.bundle.js,vendor.bundle.map(vendor)3.96 MB [initial] [rendered]

chunk {4} inline.bundle.js,inline.bundle.map(inline)0 bytes [entry] [rendered]

等待:10Mb供应商捆绑包用于这样一个简单的应用程序?

ng build --prod

哈希:09a5f095e33b2980e7cc时间:23455ms chunk {0} main.6273b0f04a07a1c2ad6c.bundle.js,main.6273b0f04a07a1c2ad6c.bundle.map(main)18.3 kB {3} [initial] [rendered]

chunk {1} styles.bfdaa4d8a4eb2d0cb019.bundle.css,styles.bfdaa4d8a4eb2d0cb019.bundle.map,styles.bfdaa4d8a4eb2d0cb019.bundle.map(styles)154 kB {4} [initial] [rendered]

chunk {2} scripts.c5b720a078e5464ec211.bundle.js,scripts.c5b720a078e5464ec211.bundle.map(scripts)128 kB {4} [initial] [rendered]

chunk {3} vendor.07af2467307e17d85438.bundle.js,vendor.07af2467307e17d85438.bundle.map(vendor)3.96 MB [initial] [rendered]

chunk {4} inline.a345391d459797f81820.bundle.js,inline.a345391d459797f81820.bundle.map(inline)0 bytes [entry] [rendered]

再等一下:这样一个类似的供应商包大小的产品?

ng build --prod --aot
Run Code Online (Sandbox Code Playgroud)

哈希:517e4425ff872bbe3e5b时间:22856ms chunk {0} main.95eadabace554e3c2b43.bundle.js,main.95eadabace554e3c2b43.bundle.map(main)130 kB {3} [initial] [rendered]

chunk {1} styles.e53a388ae1dd2b7f5434.bundle.css,styles.e53a388ae1dd2b7f5434.bundle.map,styles.e53a388ae1dd2b7f5434.bundle.map(styles)154 kB {4} [initial] [rendered]

chunk {2} scripts.e5c2c90547f3168a7564.bundle.js,scripts.e5c2c90547f3168a7564.bundle.map(scripts)128 kB {4} [initial] [rendered]

chunk {3} vendor.41a6c1f57136df286f14.bundle.js,vendor.41a6c1f57136df286f14.bundle.map(vendor)2.75 MB [initial] [rendered]

chunk {4} inline.97c0403c57a46c6a7920.bundle.js,inline.97c0403c57a46c6a7920.bundle.map(inline)0 bytes [entry] [rendered]

ng build --aot
Run Code Online (Sandbox Code Playgroud)

哈希:040cc91df4df5ffc3c3f时间:11011ms chunk {0} main.bundle.js,main.bundle.map(main)130 kB {3} [initial] [rendered]

chunk {1} styles.bundle.css,styles.bundle.map,styles.bundle.map(styles)155 kB {4} [initial] [rendered]

chunk {2} scripts.bundle.js,scripts.bundle.map(scripts)128 kB {4} [initial] [rendered]

chunk {3} vendor.bundle.js,vendor.bundle.map(vendor)2.75 MB [initial] [rendered]

chunk {4} inline.bundle.js,inline.bundle.map(inline)0 bytes [entry] [rendered]

所以在prod上部署我的应用程序的几个问题:

  • 为什么供应商捆绑这么大?
  • 树角正在摇动吗?
  • 如何改善这个捆绑尺寸?
  • 是否需要.map文件?
  • 捆绑包中是否包含测试功能?生产中我不需要它们.
  • 一般性问题:为产品打包的推荐工具是什么?也许angular-cli(在后台使用webpack)不是最合适的?我可以做更多吗?

我搜索了有关Stack Overflow的许多讨论,但我没有找到任何一般性问题.

Jac*_*ncy 55

2018年10月更新

由于这个答案有很大的吸引力,我认为最好用更新的Angular优化来更新它:

  1. 正如另一位回答者所说,ng build --prod --build-optimizer对于使用少于Angular v5的人来说,这是一个不错的选择.对于较新的版本,默认情况下会执行此操作ng build --prod
  2. 另一种选择是使用模块分块/延迟加载来更好地将应用程序拆分为更小的块
  3. 常春藤渲染引擎虽然尚未投入生产,但很快就能提供更好的捆绑尺寸
  4. 确保你的第三方派对是树可以摇动的.如果你还没有使用Rxjs v6,你应该是.
  5. 如果所有其他方法都失败了,请使用webpack-bundle-analyzer之类的工具来查看模块中导致膨胀的原因

一些声称使用AOT编译可以将供应商包大小减少到250kb.但是,在BlackHoleGalaxy的例子中,他使用了AOT编译,但仍然保留了2.75MB的供应商包大小,ng build --prod --aot比假设的250kb大10倍.即使您使用的是v4.0,这也不会超出angular2应用程序的标准.对于真正关心性能的人来说,2.75MB仍然太大,特别是在移动设备上.

您可以采取一些措施来帮助提高应用程序的性能:

1)AOT和Tree Shaking(angular-cli开箱即用)

2)使用Angular Universal AKA服务器端渲染(不在cli中)

3)Web Workers(再次,不是在cli中,而是一个非常需要的功能)
请参阅:https://github.com/angular/angular-cli/issues/2305

4)服务人员
见:https://github.com/angular/angular-cli/issues/4006

您可能不需要在单个应用程序中使用所有这些,但这些是当前用于优化Angular性能的一些选项.我相信/希望Google了解性能方面存在的缺点,并计划在未来改进这一点.

这里有一个参考,更深入地讨论了我上面提到的一些概念:

https://medium.com/@areai51/the-4-stages-of-perf-tuning-for-your-angular2-app-922ce5c1b294

  • @JacquesCornat看起来不错!但您的应用只有一个组件.问题是如何管理包大小或更大的应用程序.AOT通常不会减少捆绑尺寸,人们不得不寻求其他方式进行优化.我强烈建议大家查看webpack-bundle-analyzer.一个非常有用/简单的方法来查看导致膨胀的原因 (2认同)

Shu*_*aid 20

使用最新的angular cli版本并使用命令ng build --prod --build-optimizer 它肯定会减少 prod env的构建大小.

这就是构建优化器所做的工作:

构建优化器有两个主要工作.首先,我们能够将应用程序的某些部分标记为纯粹,这样可以改善现有工具提供的树抖动,从而删除不需要的应用程序的其他部分.

构建优化器的第二件事是从应用程序的运行时代码中删除Angular装饰器.装饰器由编译器使用,在运行时不需要,可以删除.每个作业都会减少JavaScript包的大小,并提高应用程序的启动速度.

注意:Angular 5的一个更新,ng build --prod会自动处理上面的过程:)


Eri*_*ton 13

Lodash可以为您的包提供一大块代码,具体取决于您从中导入的方式.例如:

// includes the entire package (very large)
import * as _ from 'lodash';

// depending on your buildchain, may still include the entire package
import { flatten } from 'lodash';

// imports only the code needed for `flatten`
import flatten from 'lodash-es/flatten'
Run Code Online (Sandbox Code Playgroud)

就个人而言,我仍然希望我的实用功能更小.例如,在最小化之后flatten,可以1.2K为您的捆绑做出贡献.所以我一直在构建一系列简化的lodash函数.我的实施flatten有助于实现50 bytes.你可以在这里查看它是否适合你:https://github.com/simontonsoftware/micro-dash


Jac*_*nat 11

首先,供应商捆绑是巨大的,因为Angular 2依赖于很多库.Angular 2 app的最小大小约为500KB(在某些情况下为250KB,见底部帖子).
树摇动正确使用angular-cli.
不要不包括.map文件,因为仅用于调试使用.此外,如果您使用热更换模块,请将其移除以减轻供应商的负担.

为了生产,我个人使用Webpack(而angular-cli也依赖它),因为你可以真正configure everything进行优化或调试.
如果你想使用Webpack,我同意它的第一个观点有点棘手,但是看到网上的教程,你不会失望的.
另外,使用angular-cli,这可以很好地完成工作.

使用Ahead-of-time编译对于优化应用程序是必需的,并将Angular 2应用程序缩小到250KB.

这是我创建的一个repo(github.com/JCornat/min-angular)来测试最小的Angular bundle大小,我获得了384kB.我相信有很简单的方法来优化它.

谈论大型应用程序,使用AngularClass/angular-starter配置,与上面的repo相同,我的大型应用程序(150多个组件)的捆绑包大小从8MB(没有地图文件的4MB)变为580kB.

  • 是的,webpack配置可以减少捆绑包的大小. (2认同)

Neo*_*isk 10

这里的所有答案都已过时。我刚刚使用 Angular 13 CLI 构建了 Angular 的标准样板应用程序,名为“Tour of Heroes”。最初的产品构建花了 10 秒,随后在 3 秒内完成。Gzip之前的包大小为 244kB 。我用来构建的命令是“ng build”,没有对样板项目进行任何更改。

关于这个话题有很多错误信息。让我们传播事实。

构建文件夹大小(以字节为单位),按框架划分,删除了 .map 文件,无 gzip。

  • 更新于 2023/01/18: Angular 15.1.0 - 153,803(无路由器),gzip 压缩估计为 46.05 kB。
  • 2023/01/18 更新: Angular 15.1.0 - 236,373(路由器),gzip 压缩估计 64.83 kB。
  • 更新 2022/03/02: Angular 13.2.5 - 171,580(ng 新测试应用程序,scss,无路由器)。JS 大小为 153.58kb,gzip 后估计为 46,90kb,由 CLI 控制台输出提供。
  • 更新于 2022/03/02: Angular 13.2.5 - 249,449(ng 新的 Angular-tour-of-heroes、scss、router)。JS 大小 229.49kb,gzip 后估计为 64.91kb,由 CLI 提供。
  • Angular 13.0.0 - 264,563(ng 新的 Angular-tour-of-heroes、scss、router)。
  • 没有路由器的 React 17.0.2 - 167,074 (npx create-react-app my-app)。
  • React 17.0.2 与 Router - 172,459 (npx create-react-app my-app,将 "react-router-dom": "6.0.2" 添加到 package.json,包裹<App />在里面<BrowserRouter>,如此处所述)。

在此输入图像描述

  • @DeekshithAnand:我更新了我的答案。仅增加+5KB。 (2认同)

Ren*_*abu 6

以下解决方案假设您使用nodejs为dist /文件夹提供服务.请在根级别使用以下app.js.

const express = require('express'),http = require('http'),path = require('path'),compression = require('compression');

const app = express();

app.use(express.static(path.join(__dirname, 'dist')));
app.use(compression()) //compressing dist folder 
app.get('*', (req, res) => {
  res.sendFile(path.join(__dirname, 'dist/index.html'));
})

const port = process.env.PORT || '4201';
app.set('port', port);

const server = http.createServer(app);
server.listen(port, () => console.log('Running at port ' + port))
Run Code Online (Sandbox Code Playgroud)

确保安装依赖项;

npm install compression --save
npm install express --save;
Run Code Online (Sandbox Code Playgroud)

现在构建应用程序

ng build --prod --build-optimizer
Run Code Online (Sandbox Code Playgroud)

如果你想进一步压缩构建说减少300kb(大约),那么按照下面的过程;

创建一个vendor在src文件夹内部调用的文件夹,在vendor文件夹中创建一个文件rxjs.ts 并将下面的代码粘贴到其中;

export {Subject} from 'rxjs/Subject';
export {Observable} from 'rxjs/Observable';
export {Subscription} from 'rxjs/Subscription';
Run Code Online (Sandbox Code Playgroud)

然后tsconfig.json在angular-cli应用程序中添加文件中的follwing .然后在compilerOptions,添加以下json;

"paths": {
      "rxjs": [
        "./vendor/rxjs.ts"
      ]
    }
Run Code Online (Sandbox Code Playgroud)

这将使您的构建大小变得太小.在我的项目中,我将大小从11mb缩小到1mb.希望能帮助到你


Hie*_*ran 6

更新:2022/05/23,角度 14 (RC1)

g-zip这ng build --prod是两个非常有帮助的解决方案。这会对你有很大帮助。但如果你做了任何事,尽了最大努力呢?还是不行?使用延迟加载模块。还是不行?

这是为您提供的答案。目前,我正在使用 nx 将我的 Angular 13 项目升级到 Angular 14 项目,我发现“桶副作用”会导致你的main.js捆绑包增加。解决方案很简单。

  1. tsconfig.json将构建模块从更改"module": "commonjs"为"module": "es2020"或 esnext (您应该使用 es2020 在这里解释https://web.archive.org/web/20220605011837/https://angular.io/guide/migration-update-module-and-target-compiler -选项)

在此输入图像描述

  1. 添加sideEffects: false并package.json查看结果:

在此输入图像描述

为什么?

完整的解释在这里https://webpack.js.org/guides/tree-shaking/#conclusion和这里https://github.com/angular/angular-cli/issues/16799和这里https://stackoverflow.com /a/59353152/5748537。但我可以简短地告诉你:

你有模块“A 是小”,“B 是大”。您将它们写入 UI 库并将它们导出到index.ts文件中。您将 A 导入到您的项目中。最终捆绑包仍然包含您不想要的 B。

为什么?

因为commonjs不聪明。使用es2020更好,他们知道哪些是使用,哪些不是。但他们不确定是否应该删除它。您添加sideEffects: false告诉他们:“清除死代码是安全的”。他们做到了。那么你的包就很小了。这可以在任何现代 JS 框架中使用,包括 React、VueJS

在这里阅读角度项目中有关桶副作用的问题:https://github.com/angular/angular-cli/issues/16799

p/s:我的生产角度网站在这里: https: //awread.vn,每天有 100 个用户。


kwa*_*ski 5

我想分享的一件事是导入的库如何增加dist的大小。我已经导入了angular2-moment软件包,但是我可以使用从@ angular / common导出的标准DatePipe进行所需的所有日期时间格式化。

使用Angular2-Moment "angular2-moment": "^1.6.0",

块{0} polyfills.036982dc15bb5fc67cb8.bundle.js(polyfills)191 kB {4} [initial] [rendered]块{1} main.e7496551a26816427b68.bundle.js(main)2.2 MB {3} [initial] [rendered]块{2} styles.056656ed596d26ba0192.bundle.css(样式)69个字节{4} [initial] [rendered]块{3} vendor.62c2cfe0ca794a5006d1.bundle.js(供应商)3.84 MB [initial] [rendered]块{4 } inline.0b9c3de53405d705e757.bundle.js(内联)0个字节[输入] [呈现]

删除Angular2-moment并改用DatePipe之后

块{0} polyfills.036982dc15bb5fc67cb8.bundle.js(polyfills)191 kB {4} [initial] [rendered]块{1} main.f2b62721788695a4655c.bundle.js(main)2.2 MB {3} [initial] [rendered]块{2} styles.056656ed596d26ba0192.bundle.css(样式)69字节{4} [initial] [rendered]块{3} vendor.e1de06303258c58c9d01.bundle.js(供应商)3.35 MB [initial] [rendered]块{4 } inline.3ae24861b3637391ba70.bundle.js(内联)0个字节[输入] [呈现]

请注意,供应商捆绑包减少了一半兆字节!

值得一提的是,即使您已经熟悉外部库,也值得检查一下角度标准软件包可以做什么。


Ste*_*lec 5

另一种减少捆绑的方法是提供 GZIP 而不是 JS。我们从 2.6mb 增加到 543ko。

https://httpd.apache.org/docs/2.4/mod/mod_deflate.html