我最近在 Angular 12 项目中遇到了包大小超出预算限制的错误。在实施多种方法来减小包大小的同时,差异加载就是这样一种方式。 Angular 默认提供此功能,并在您在 target
和 es2015
配置中将 tsconfig.app.json
设置为 .browserslistrc
后为您启用此功能。
但令我惊讶的是,即使在执行上述两个步骤后,某些内容仍然无法正常工作。我们使用 @angular-builders/custom-webpack
作为我们的构建器。在我们的自定义 webpack 配置中,我们只是使用 DefinePlugin
添加一些特定于环境的变量。
我的angular.json:
"architect": {
"build": {
"builder": "@angular-builders/custom-webpack:browser",
"options": {
"outputPath": "dist/apps/my-project",
"index": "apps/my-project/src/index.html",
"main": "apps/my-project/src/main.ts",
"polyfills": "apps/my-project/src/polyfills.ts",
"tsConfig": "apps/my-project/tsconfig.app.json",
"aot": true,
"customWebpackConfig": {
"path": "apps/my-project/webpack.config.js",
"mergeRules": {
"externals": "replace"
}
}
},
"configurations": {
"prod": {
"outputPath": "dist/apps/my-project-prod",
"customWebpackConfig": {
"path": "apps/my-project/webpack.prod.partial.js",
"mergeRules": {
"externals": "replace"
}
},
"baseHref": "https://my-project.com/",
"fileReplacements": [
{
"replace": "apps/my-project/src/environments/environment.ts",
"with": "apps/my-project/src/environments/environment.prod.ts"
}
],
"index": {
"input": "apps/my-project/src/index.prod.html",
"output": "/index.html"
},
"optimization": true,
"outputHashing": "all",
"sourceMap": false,
"namedChunks": false,
"aot": true,
"extractLicenses": true,
"vendorChunk": false,
"buildOptimizer": true,
"budgets": [
{
"type": "initial",
"maximumWarning": "2mb",
"maximumError": "5mb"
}
]
}
}
},
"serve": {
"builder": "@angular-builders/custom-webpack:dev-server",
"options": {
"host": "localhost",
"baseHref": "http://localhost:3000",
"port": 3000,
"browserTarget": "my-project:build"
},
"configurations": {
"prod": {
"browserTarget": "my-project:build:prod"
}
}
}
}
我的tsconfig.app.json:
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "../../dist/out-tsc/apps/my-project",
"types": ["node"],
"typeRoots": [
"./src/customTypes"
]
},
"exclude": [
"src/test.ts",
"**/*.spec.ts"
],
"files": [
"src/main.ts",
"src/polyfills.ts",
],
"include": [
"src/**/*.ts"
]
}
父 tsconfig.json:
{
"compileOnSave": false,
"compilerOptions": {
"inlineSources": true,
"sourceMap": true,
"declaration": false,
"moduleResolution": "node",
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"importHelpers": true,
"target": "es2015",
"module": "es2020",
"typeRoots": [
"node_modules/@types"
],
"lib": [
"es2018",
"dom"
],
"skipLibCheck": true,
"skipDefaultLibCheck": true,
"baseUrl": "./"
},
"exclude": [
"node_modules",
"tmp"
]
}
我的.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
not IE 11
根据 docs,您可以通过查看 index.html
文件的 <script>
标签来验证差异加载是否有效:
<body>
<app-root></app-root>
<script src="runtime-es2015.js" type="module"></script>
<script src="runtime-es5.js" nomodule></script>
<script src="polyfills-es2015.js" type="module"></script>
<script src="polyfills-es5.js" nomodule></script>
<script src="styles-es2015.js" type="module"></script>
<script src="styles-es5.js" nomodule></script>
<script src="vendor-es2015.js" type="module"></script>
<script src="vendor-es5.js" nomodule></script>
<script src="main-es2015.js" type="module"></script>
<script src="main-es5.js" nomodule></script>
</body>
我的 index.html
的 <script>
标签如下所示:
<script src="runtime.f03314b4ecbf857f30db.js" defer></script>
<script src="polyfills.b4a4dc722533999c6a79.js" defer></script>
<script src="scripts.d0fcd864b87b7eb9e1e6.js" defer></script>
<script src="vendor.2070a0076d5aa66a3b91.js" defer></script>
<script src="main.c7fdac1323ac33ecb488.js" defer></script>
我似乎在其中找不到 es5
或 es2015
关键字。我也找不到 type=module
或 nomodule
。我的包大小肯定减少了,但我的项目在服务器上或部署后都不起作用。我在浏览器 (Chrome 91.0.4472.101
) 的控制台中收到以下错误,该错误不清楚:
我的polyfill.ts:
import 'core-js/es/reflect';
import '@angular/localize/init';
import 'zone.js/dist/zone';
(window as any)['global'] = window;
我遇到了这个 issue,它指出在服务期间不会发生差异加载,但对我来说它在部署后也不起作用。为了避免任何配置错误,我还在 Angular 12 中创建了一个新的演示项目,并且一切正常。我还匹配了上述文件的值。我发现的唯一区别是:
polyfill.ts
仅包含 Zone.js 的导入即使是演示项目的 index.html
也不包含 es5
、es2015
、module
、nomodule
关键字并且与我的项目相似index.html
。
我在这方面花了很多时间,但找不到任何解决方案。如果我遗漏了什么,请告诉我。