如何减小产品捆束尺寸?


135

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

它显示一些与3条路线有关的页面。我有3个组成部分。在这个页面上我使用一个lodash与角2 HTTP模块来获取一些数据(使用RxJS ObservableS,mapsubscribe)。我使用简单的显示这些元素*ngFor

但是,尽管事实上我的应用程序非常简单,但我还是得到了一个庞大的捆绑包和地图。我不是在谈论gzip版本,而是gzip压缩之前的大小。这个问题只是一般性建议查询。

一些测试结果:

ng构建

哈希:8efac7d6208adb8641c1时间:10129毫秒块{0} main.bundle.js,main.bundle.map(主要)18.7 kB {3} [初始] [呈现]

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

块{2} scripts.bundle.js,scripts.bundle.map(脚本)128 kB {4} [初始] [呈现]

块{3} vendor.bundle.js,vendor.bundle.map(供应商)3.96 MB [初始] [呈现]

块{4} inline.bundle.js,inline.bundle.map(内联)0字节[输入] [呈现]

等待:10Mb的供应商捆绑包是否提供了如此简单的应用程序?

ng build --prod

哈希:09a5f095e33b2980e7cc时间:23455ms块{0} main.6273b0f04a07a1c2ad6c.bundle.js,main.6273b0f04a07a1c2ad6c.bundle.map(主要)18.3 kB {3} [初始] [呈现]

块{1} styles.bfdaa4d8a4eb2d0cb019.bundle.css,styles.bfdaa4d8a4eb2d0cb019.bundle.map,styles.bfdaa4d8a4eb2d0cb019.bundle.map(样式)154 kB {4} [initial]

块{2} scripts.c5b720a078e5464ec211.bundle.js,scripts.c5b720a078e5464ec211.bundle.map(脚本)128 kB {4} [初始] [呈现]

块{3} vendor.07af2467307e17d85438.bundle.js,vendor.07af2467307e17d85438.bundle.map(供应商)3.96 MB [初始] [呈现]

块{4} inline.a345391d459797f81820.bundle.js,inline.a345391d459797f81820.bundle.map(内联)0个字节[输入] [呈现]

再等一遍:如此类似的供应商捆绑产品尺寸?

ng build --prod --aot

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

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

块{2} scripts.e5c2c90547f3168a7564.bundle.js,scripts.e5c2c90547f3168a7564.bundle.map(脚本)128 kB {4} [初始] [呈现]

块{3} vendor.41a6c1f57136df286f14.bundle.js,vendor.41a6c1f57136df286f14.bundle.map(供应商)2.75 MB [初始] [呈现]

块{4} inline.97c0403c57a46c6a7920.bundle.js,inline.97c0403c57a46c6a7920.bundle.map(内联)0个字节[输入] [呈现]

ng build --aot

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

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

块{2} scripts.bundle.js,scripts.bundle.map(脚本)128 kB {4} [初始] [呈现]

块{3} vendor.bundle.js,vendor.bundle.map(供应商)2.75 MB [初始] [呈现]

块{4} inline.bundle.js,inline.bundle.map(内联)0字节[输入] [呈现]

因此,在产品上部署我的应用程序时要注意几个问题:

  • 为什么供应商捆绑包如此庞大?
  • 是否适当地使用了摇树机angular-cli
  • 如何提高捆绑包的尺寸?
  • 是否需要.map文件?
  • 捆绑包中是否包含测试功能?我在生产中不需要它们。
  • 通用问题:为产品打包的推荐工具是什么?也许angular-cli(在后台使用Webpack)不是最佳选择?我们可以做得更好吗?

我搜索了关于堆栈溢出的许多讨论,但没有发现任何一般性问题。


要了解有关angular 2应用优化的更多信息,请查看以下内容:github.com/mgechev/angular-performance-checklist#introduction
Timathon

1
但是我认为我们不应该那么在乎,angular-cli会发展,事情会做得越来越好。如果您需要angular-cli没有的某些功能,只需在其回购中提交问题:github.com/angular/angular-cli
Timathon

虽然我认为@Timathon在某些方面是正确的,但如果有人尝试将Angular2部署到生产环境中,他们应该关心捆绑包的大小,因为这直接影响应用程序的性能。角度性能检查表是查看可以改进的重要资源。角度小组正在努力减少束的尺寸。激动地看到它的去向!
杰克·克兰西

Answers:


72

2020年2月更新

既然这个答案很受关注,我认为最好用更新的Angular优化来更新它:

  1. 就像另一个回答者所说的,ng build --prod --build-optimizer对于使用少于Angular v5的人来说是一个不错的选择。对于较新的版本,默认情况下使用ng build --prod
  2. 另一个选择是使用模块分块/延迟加载来更好地将应用程序拆分为较小的块
  3. Ivy渲染引擎默认在Angular 9中提供,它提供了更好的捆绑包大小
  4. 确保您的第三方部门可摇树。如果您尚未使用Rxjs v6,则应该使用。
  5. 如果所有其他方法均失败,请使用诸如webpack-bundle-analyzer之类的工具查看导致模块膨胀的原因
  6. 检查文件是否已压缩

一些人声称使用AOT编译可以将供应商捆绑包大小减小到250kb。但是,在BlackHoleGalaxy的示例中,他使用AOT编译,并且仍然剩下2.75MB的供应商捆绑包ng build --prod --aot,其容量比预期的250kb大10倍。即使您使用的是v4.0,这也不是超出angular2应用程序的标准。对于任何真正关心性能的人(尤其是在移动设备上),2.75MB的容量仍然太大。

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

1)AOT和Tree Shaking(angular-cli开箱即用)。在生产和开发环境中,默认情况下使用Angular 9 AOT。

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


我的最小项目是384kB,请参阅github.com/JCornat/min-angular我敢肯定有一种简单的方法可以对其进行优化,但是它接近250kB!
雅克·科纳特

2
@JacquesCornat看起来不错!但是您的应用程序只有一个组件。问题是如何管理捆绑包大小或更大的应用程序。通常,AOT无法充分减小捆绑包的大小,人们不得不寻找其他方式进行优化。我强烈建议大家检查一下webpack-bundle-analyzer。一种非常有用/轻松的方法来查看引起膨胀的原因
Jack Clancy

不幸的是,诸如公用事业之类的实用程序sw-precache拒绝处理大于2MB的供应商捆绑包。

1
@JackClancy“问题是如何管理包大小或更大的应用程序”。他的问题不是“如何改善捆绑包的大小?” 他正在谈论他的最小应用程序,其中包含3个组件。无论如何,使用AngularClass / angular-starter配置谈论大型捆绑包时,与我的回购协议一样,大型应用程序的捆绑包大小从8MB(无地图文件的4MB)增加到580kB。
雅克·科纳特

1
谢谢,你救了我。--prod将应用程序大小从6Mb减少到1.2Mb。仍不完美,但可以接受,因为它仅用于桌面。
Vyacheslav Tsivina,

21

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

这是构建优化器在后台执行的操作:

构建优化器有两个主要任务。首先,我们能够将您的应用程序的各个部分标记为纯净的,这改善了现有工具所提供的抖动,从而消除了应用程序不需要的其他部分。

生成优化器所做的第二件事是从应用程序的运行时代码中删除Angular装饰器。装饰器由编译器使用,运行时不需要,可以将其删除。这些作业中的每一个都会减小JavaScript捆绑包的大小,并提高用户应用程序的启动速度。

注意:Angular 5及更高版本的一个更新,将ng build --prod自动完成上述过程:)


1
至于目前的角度6,供应商仍然只有4MB的空间用于仅安装角度/材质和火力点
FindOutIslamNow

即使我遇到了这个错误,这也是角度/材质的问题。未正确摇树可能是根本原因。使用新的渲染器引擎IVY可能会解决。
Shubhendu Vaid

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'

我个人仍然希望从实用程序功能中获得更小的空间。例如,在最小化之后flatten可以1.2K为您的捆绑包做出贡献。因此,我一直在构建简化的lodash函数的集合。我对的flatten贡献左右50 bytes。您可以在此处查看它是否适合您:https : //github.com/simontonsoftware/micro-dash


1
2 /我尝试了上面评论中的“ loadash-es”技巧。它减少了我的捆绑包大小0.08mb。
Stefdelec '18

那不多!您还有其他以旧方式导入lodash的东西吗?除非所有内容都以新方式导入,否则您将不会获得任何帮助。
埃里克·西蒙顿

我想我已经取代了一切。大小不会改变。我在下面提供了另一个提示(gzip的东西),它确实对我们有所帮助。
Stefdelec

有趣。lodash为您的捆绑包贡献了多少?(例如,使用source-map-explorer。)
埃里克·西蒙顿

11

首先,供应商捆绑包之所以庞大是因为Angular 2依赖于许多库。Angular 2应用程序的最小大小约为500KB(在某些情况下为250KB,请参见底部帖子)。
树木适当地使用摇树angular-cli
不要包括.map文件,因为只有用于调试。此外,如果您使用热更换模块,请卸下它以减轻供应商的负担。

为了进行生产打包,我个人使用Webpack(而且angular-cli也依赖于Webpack),因为您确实可以configure everything进行优化或调试。
如果您想使用Webpack,我同意它的初学者有点棘手,但是请参阅网上的教程,不会感到失望。
否则,请使用angular-cli,可以很好地完成工作。

必须使用提前编译才能优化应用程序,并将Angular 2应用程序缩小到250KB

这是我创建的一个回购协议(github.com/JCornat/min-angular),用于测试最小的Angular bundle大小,我得到384kB。我敢肯定有一种简单的方法可以对其进行优化。

在使用AngularClass / angular-starter配置谈论大型应用程序时,与上面的存储库相同,大型应用程序(150多个组件)的捆绑包大小从8MB(无地图文件的4MB)增加到580kB


什么是特定的角度启动器配置可帮助减小套件尺寸?是webpack.config吗?
MartinJH

2
是的,这是webpack配置减小了捆绑包的大小。
雅克·科纳特

感谢您的澄清:)
MartinJH

8

以下解决方案假定您正在使用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))

确保安装依赖项;

npm install compression --save
npm install express --save;

现在建立应用程式

ng build --prod --build-optimizer

如果要进一步压缩构建,请说从中减少300kb(approx),然后执行以下过程;

创建一个文件夹,名为vendor里面src的文件夹和内部供应商文件夹中创建一个文件,rxjs.ts 并粘贴在下面的代码它;

export {Subject} from 'rxjs/Subject';
export {Observable} from 'rxjs/Observable';
export {Subscription} from 'rxjs/Subscription';

然后将以下内容添加到tsconfig.json您的angular-cli应用程序的文件中。然后在中compilerOptions添加以下json;

"paths": {
      "rxjs": [
        "./vendor/rxjs.ts"
      ]
    }

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


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个字节[输入] [呈现]

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

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



1

如果您已经运行ng build --prod-完全不应该有vendor文件。

如果我只是运行ng build-我得到以下文件:

在此处输入图片说明

该文件夹的总大小约为14MB。哇!:D

但是,如果我运行ng build --prod-我会得到以下文件:

在此处输入图片说明

文件夹的总大小为584K。

一个和相同的代码。在这两种情况下,我都启用了常春藤。角度为8.2.13。

所以-我猜您没有添加--prod到构建命令中?


1

如果您使用的是Angular 8+,并且想要减小捆绑包的大小,则可以使用Ivy。常春藤是Angular 9中的默认视图引擎。只需转到src / tsconfig.app.json并添加angularCompilerOptions参数即可,例如:

{
  "extends": ...,
  "compilerOptions":...,
  "exclude": ...,

/* add this one */ 
  "angularCompilerOptions": {
    "enableIvy": true
  }
}

1

在我看来,这确实减小了尺寸:

ng build --prod --build-optimizer --optimization.

对于Angular 5+ ng-build --prod默认情况下会这样做。运行此命令后的大小从1.7MB减小到1.2MB,但不足以满足我的生产目的。

我在facebook Messenger平台上工作,messenger应用程序需要小于1MB才能在Messenger平台上运行。一直在努力寻找有效的摇树方法,但仍然没有运气。



0

我有一个角度5 +弹簧启动应用程序(application.properties 1.3+),借助压缩功能(下面提供了链接)能够将main.bundle.ts的大小从2.7 MB减少到530 KB。

同样,默认情况下,--aot和--build-optimizer是通过--prod模式启用的,无需分别指定它们。

https://stackoverflow.com/a/28216983/9491345


0

检查您是否已将ng build --prod的配置命名为“ production”,因为它是ng build --configuration = production的简写。 没有答案解决了我的问题,因为问题就在屏幕的前面。我认为这可能很普遍...我已经通过i18n将所有配置重命名为Production-en来使该应用程序国际化。然后,我使用ng build --prod进行了构建,并假设使用了默认优化,并且应该接近最佳值,但实际上仅执行ng build导致7mb捆绑包,而不是250kb。


0

取自angular docs v9(https://angular.io/guide/workspace-config#alternate-build-configurations):

默认情况下,定义了生产配置,并且ng build命令具有--prod选项,该选项使用此配置进行构建。生产配置会设置默认值,这些默认值可以通过多种方式优化应用程序,例如,捆绑文件最小化多余的空格删除注释和无效代码以及重写代码以使用简短的,隐秘的名称(最小化)。

另外,您可以使用@ angular-builders / custom-webpack:browser构建器压缩所有可部署的内容,其中您的自定义webpack.config.js如下所示:

module.exports = {
  entry: {
  },
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: '[name].[hash].js'
  },
  plugins: [
    new CompressionPlugin({
      deleteOriginalAssets: true,
    })
  ]
};

之后,您将必须配置Web服务器以提供压缩内容,例如,必须使用nginx添加到nginx.conf中:

server {
    gzip on;
    gzip_types      text/plain application/xml;
    gzip_proxied    no-cache no-store private expired auth;
    gzip_min_length 1000;
    ...
}

在我的情况下,仅使用--prod in ng版本后,dist文件夹从25 mb缩小到5 mb,然后在压缩后进一步缩小到1.5 mb。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.