我有一个简单的应用程序,由 angular-cli
初始化。
它显示一些与 3 条路线相关的页面。我有 3 个组件。在此页面的其中一个页面上,我使用 lodash
和 Angular 2 HTTP 模块来获取一些数据(使用 RxJS Observable
s、map
和 subscribe
)。我使用简单的 *ngFor
显示这些元素。
但是,尽管我的应用程序非常简单,但我得到了一个巨大的(在我看来)捆绑包和地图。我不谈论 gzip 版本,而是谈论 gzip 之前的大小。这个问题只是一个一般性的建议查询。
一些测试结果:
构建
哈希:8efac7d6208adb8641c1 时间:10129ms 块 {0} main.bundle.js,main.bundle.map(主)18.7 kB {3} [初始] [渲染] 块 {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 块 {0} main.6273b0f04a07a1c2ad6c.bundle.js, main.6273b0f04a07a1c2ad6c.bundle.map (main) 18.3 kB {3} [initial] [rendered] chunk {1} styles.bfdaa4d8a.cs4styles.bfdaa4d8a.cs4 , styles.bfdaa4d8a4eb2d0cb019.bundle.map, styles.bfdaa4d8a4eb2d0cb019.bundle.map (styles) 154 kB {4} [initial] [rendered] chunk {2} scripts.c5b720a078e5464ec211.bundle.js, scripts.c5b720a078e5464ec211.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 (inline) 0 bytes [entry] [rendered]
再等一下:prod 的供应商捆绑大小如此相似?
ng build --prod --aot
哈希:517e4425ff872bbe3e5b 时间:22856ms 块 {0} main.95eadbace554e3c2b43.bundle.js,main.95eadbace554e3c2b43.bundle.map(主)130 kB {3} [初始] [渲染] 块 {1} styles.e53a388ae1dd2b7f543. , styles.e53a388ae1dd2b7f5434.bundle.map, styles.e53a388ae1dd2b7f5434.bundle.map (styles) 154 kB {4} [initial] [rendered] chunk {2} scripts.e5c2c90547f3168a7564.bundle.js, scripts.e5c2c90547f3168a755.脚本)128 kB {4} [initial] [rendered] chunk {3} vendor.41a6c1f57136df286f14.bundle.js, vendor.41a6c1f57136df286f14.bundle.map(供应商)2.75 MB [initial] [rendered] chunk {4} inline.97c0403c57a46c6a7920 .bundle.js, inline.97c0403c57a46c6a7920.bundle.map (inline) 0 bytes [entry] [rendered]
ng build --aot
哈希:040cc91df4df5ffc3c3f 时间:11011 毫秒块 {0} main.bundle.js,main.bundle.map(主)130 kB {3} [初始] [渲染] 块 {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 ]
所以有几个关于在产品上部署我的应用程序的问题:
为什么供应商捆绑包如此庞大?
angular-cli 是否正确使用摇树?
如何提高这个捆绑包的大小?
是否需要 .map 文件?
捆绑包中是否包含测试功能?我在产品中不需要它们。
一般问题:推荐的产品包装工具是什么?也许 angular-cli(在后台使用 Webpack)不是最好的选择?我们能做得更好吗?
我在 Stack Overflow 上搜索了很多讨论,但没有找到任何通用问题。
2020 年 2 月更新
由于这个答案有很大的吸引力,我认为最好用更新的 Angular 优化来更新它:
正如另一位回答者所说, ng build --prod --build-optimizer 对于使用低于 Angular v5 的人来说是一个不错的选择。对于较新的版本,默认情况下这是使用 ng build --prod 完成的另一个选项是使用模块分块/延迟加载来更好地将应用程序拆分为更小的块 Ivy 渲染引擎默认出现在 Angular 9 中,它提供了更好的包大小确保你的第 3 方部门是可摇树的。如果你还没有使用 Rxjs v6,你应该使用。如果一切都失败了,请使用 webpack-bundle-analyzer 之类的工具来查看导致模块膨胀的原因 检查文件是否已压缩
有人声称使用 AOT 编译可以将供应商捆绑包大小减少到 250kb。然而,在 BlackHoleGalaxy 的示例中,他使用了 AOT 编译,并且仍然留下了带有 ng build --prod --aot
的 2.75MB 的供应商包大小,比假定的 250kb 大 10 倍。即使您使用的是 v4.0,这也不是 angular2 应用程序的标准。对于真正关心性能的人来说,2.75MB 仍然太大了,尤其是在移动设备上。
您可以做一些事情来帮助提高应用程序的性能:
1) AOT & Tree Shaking(angular-cli 开箱即用)。使用 Angular 9,AOT 默认在 prod 和 dev 环境中。
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 性能的一些选项。我相信/希望谷歌意识到在性能方面的开箱即用缺陷,并计划在未来改进这一点。
这是一个参考,更深入地讨论了我上面提到的一些概念:
https://medium.com/@areai51/the-4-stages-of-perf-tuning-for-your-angular2-app-922ce5c1b294
使用最新的 Angular cli 版本并使用命令 ng build --prod --build-optimizer 它肯定会减少 prod env 的构建大小。
这就是构建优化器在后台所做的:
构建优化器有两个主要工作。首先,我们能够将应用程序的某些部分标记为纯,这改进了现有工具提供的摇树,删除了应用程序中不需要的其他部分。
构建优化器所做的第二件事是从应用程序的运行时代码中删除 Angular 装饰器。装饰器由编译器使用,在运行时不需要并且可以删除。这些作业中的每一个都会减小 JavaScript 包的大小,并为用户提高应用程序的启动速度。
注意:Angular 5 及更高版本的一次更新,ng build --prod
会自动处理上述过程 :)
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
source-map-explorer
。)
首先,供应商捆绑包非常庞大,仅仅是因为 Angular 2 依赖于很多库。 Angular 2 app is around 500KB 的最小大小(在某些情况下为 250KB,请参阅底部帖子)。
angular-cli
正确使用摇树。
不包含 .map
文件,因为使用过仅用于调试。此外,如果您使用热更换模块,请将其移除以减轻供应商的负担。
为了打包生产,我个人使用 Webpack(angular-cli 也依赖它),因为您真的可以 configure everything
进行优化或调试。
如果您想使用 { 3},我同意第一次看有点棘手,但是看看网上的教程,你不会失望的。
否则,使用angular-cli
,它可以很好地完成工作。
必须使用 Ahead-of-time compilation 来优化应用,并将 Angular 2 应用缩小到 250KB。
这是我创建的一个存储库 (github.com/JCornat/min-angular),用于测试最小的 Angular 包大小,我获得了 384kB。我相信有简单的方法来优化它。
谈到大型应用程序,使用 AngularClass/angular-starter 配置,与上面的 repo 相同,我的大型应用程序包大小(150+ 组件)从 8MB(4MB没有地图文件)到 580kB。
以下解决方案假设您使用 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(约),请按照以下过程操作;
在 src
文件夹中创建一个名为 vendor
的文件夹,在 vendor 文件夹中创建一个文件 rxjs.ts
并将以下代码粘贴到它;
export {Subject} from 'rxjs/Subject';
export {Observable} from 'rxjs/Observable';
export {Subscription} from 'rxjs/Subscription';
然后在您的 angular-cli 应用程序的 tsconfig.json
文件中添加以下内容。然后在 compilerOptions
中,添加以下 json;
"paths": {
"rxjs": [
"./vendor/rxjs.ts"
]
}
这将使您的构建尺寸太小。在我的项目中,我将大小从 11mb 减小到了 1mb。希望能帮助到你
这里的所有答案都已过时。我刚刚使用 Angular 13 CLI 构建了名为“英雄之旅”的 Angular 标准样板应用程序。初始产品构建耗时 10 秒,随后在 3 秒内完成。 Gzip 之前的包大小为 244kB。我用来构建的命令是“ng build”,对样板项目没有任何更改。
关于这个话题有很多错误信息。让我们传播事实。
构建文件夹大小,以字节为单位,按框架,.map 文件被删除,没有 gzip。
更新 2022/03/02:Angular 13.2.5 - 171,580(ng 新的测试应用程序,scss,无路由器)。 JS 大小 153.58kb,压缩后估计为 46,90kb,由 CLI 控制台输出提供。
更新 2022/03/02:Angular 13.2.5 - 249,449(ng 新的 angular-tour-of-heroes、scss、路由器)。 JS 大小 229.49kb,gzip 估计为 64.91kb,由 CLI 提供。
Angular 13.0.0 - 264,563(ng 新的 angular-tour-of-heroes、scss、路由器)。
没有路由器的 React 17.0.2 - 167,074 (npx create-react-app my-app)。
React 17.0.2 with Router - 172,459(npx create-react-app my-app,将 "react-router-dom": "6.0.2" 添加到 package.json,将
https://i.stack.imgur.com/93das.png
我想分享的一件事是导入的库如何增加 dist 的大小。我导入了 angular2-moment 包,而我可以使用从 @angular/common 导出的标准 DatePipe 进行所需的所有日期时间格式化。
使用 Angular2-Moment "angular2-moment": "^1.6.0",
块 {0} polyfills.036982dc15bb5fc67cb8.bundle.js (polyfills) 191 kB {4} [初始] [渲染] 块 {1} main.e7496551a26816427b68.bundle.js (main) 2.2 MB {3} [初始] [渲染]块 {2} styles.056656ed596d26ba0192.bundle.css(样式)69 字节 {4} [初始] [渲染] 块 {3} vendor.62c2cfe0ca794a5006d1.bundle.js(供应商)3.84 MB [初始] [渲染] 块 {4 } inline.0b9c3de53405d705e757.bundle.js (inline) 0 bytes [entry] [rendered]
删除 Angular2-moment 并改用 DatePipe 后
块 {0} polyfills.036982dc15bb5fc67cb8.bundle.js (polyfills) 191 kB {4} [初始] [渲染] 块 {1} main.f2b62721788695a4655c.bundle.js (main) 2.2 MB {3} [初始] [渲染]块 {2} styles.056656ed596d26ba0192.bundle.css(样式)69 字节 {4} [初始] [渲染] 块 {3} vendor.e1de06303258c58c9d01.bundle.js(供应商)3.35 MB [初始] [渲染] 块 {4 } inline.3ae24861b3637391ba70.bundle.js (inline) 0 bytes [entry] [rendered]
请注意,供应商捆绑包减少了半兆字节!
即使您已经熟悉外部库,也值得检查 Angular 标准包可以做什么。
它的作品 100% ng build --prod --aot --build-optimizer --vendor-chunk=true
如果您已运行 ng build --prod
- 您根本不应该有 vendor
文件。
如果我只运行 ng build
- 我会得到这些文件:
https://i.stack.imgur.com/PU6IF.png
该文件夹的总大小约为 14MB。哇! :D
但是如果我运行 ng build --prod
- 我会得到这些文件:
https://i.stack.imgur.com/QMVxv.png
文件夹的总大小为 584K。
一个和相同的代码。在这两种情况下,我都启用了 Ivy。角度是 8.2.13。
所以 - 我猜你没有将 --prod
添加到你的构建命令中?
如果您使用的是 Angular 8+,并且想要减小包的大小,您可以使用 Ivy。 Ivy 是 Angular 9 中的默认视图引擎,只需转到 src/tsconfig.app.json 并添加 angularCompilerOptions 参数,例如:
{
"extends": ...,
"compilerOptions":...,
"exclude": ...,
/* add this one */
"angularCompilerOptions": {
"enableIvy": true
}
}
在我的情况下,这确实减小了尺寸:
ng build --prod --build-optimizer --optimization.
对于 Angular 5+ ng-build --prod 默认执行此操作。运行此命令后的大小从 1.7MB 减少到 1.2MB,但不足以满足我的生产目的。
我在 facebook messenger 平台上工作,messenger 应用程序需要小于 1MB 才能在 messenger 平台上运行。一直试图找出有效的摇树解决方案,但仍然没有运气。
取自 angular docs v9 (https://angular.io/guide/workspace-config#alternate-build-configurations):
默认情况下,定义了生产配置,并且 ng build 命令具有使用此配置构建的 --prod 选项。生产配置设置默认值,以多种方式优化应用程序,例如捆绑文件、最小化多余的空格、删除注释和死代码,以及重写代码以使用简短、神秘的名称(“缩小”)。
此外,您可以使用 @angular-builders/custom-webpack:browser builder 压缩所有可部署文件,其中您的自定义 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;
...
}
在我的例子中,dist 文件夹在 ng build 中使用 --prod 后从 25 缩小到 5 mb,然后在压缩后进一步缩小到 1.5 mb。
更新:2022/05/23,角度 14 (RC1)
g-zip
和 ng build --prod
是两个非常有用的解决方案。这会对你有很大帮助。但如果,你做了什么,尽力而为。它仍然不起作用?使用延迟加载模块。还是不行?
这是给你的答案。目前我正在使用 nx 将我的 Angular 13 升级到 Angular 14 项目,我发现“桶副作用”会导致您的 main.js
捆绑包增加。解决方案很简单。
将 tsconfig.json 构建模块从 "module": "commonjs" 更改为 "module": "es2020" 或 esnext(你应该使用 es2020 在这里解释 https://web.archive.org/web/20220605011837/https:// angular.io/guide/migration-update-module-and-target-compiler-options)
https://i.stack.imgur.com/WhTlE.png
将 sideEffects: false 添加到 package.json 并查看结果:
https://i.stack.imgur.com/9m26L.png
为什么?
完整的解释在这里 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
在 Angular 项目中阅读有关桶副作用的问题:https://github.com/angular/angular-cli/issues/16799
p/s:我的生产 Angular 网站在这里:https://awread.vn,每天有 100 个用户。
not found
我有一个 Angular 5 + spring boot 应用程序(application.properties 1.3+),借助压缩(下面附加的链接)能够将 main.bundle.ts 的大小从 2.7 MB 减小到 530 KB。
此外,默认情况下 --aot 和 --build-optimizer 使用 --prod 模式启用,您无需单独指定它们。
https://stackoverflow.com/a/28216983/9491345
检查您是否为 ng build --prod 配置了名为“production”的配置,因为它是 ng build --configuration=production 的简写。没有答案解决了我的问题,因为问题就在屏幕前。我认为这可能很常见......我已经使用 i18n 将应用程序国际化,将所有配置重命名为例如 production-en。然后我使用 ng build --prod 进行构建,假设使用了默认优化并且应该接近最优,但实际上只执行了 ng build 导致 7mb 包而不是 250kb。
sw-precache
等实用程序拒绝处理大于 2MB 的供应商捆绑包。