Angular-cli:如何忽略 class 名字被缩小
Angular-cli : How to ignore class names from being minified
对于应用程序,我们需要保持 class 名称不缩小,因为我们使用
var className = myObject.constructor.name;
export class myObject{ ... }
当我们运行
ng 构建 -- pro
class 名称被缩小为随机名称。
Angular cli 在内部使用 webpack 和 uglify。一种解决方案是通过导出 webpack 配置来更改 uglify 中的选项。你可以通过 运行 ng eject 和 ng eject --prod
查看 webpack 文件
new UglifyJsPlugin({
"mangle": false,
"compress": {
"screw_ie8": true,
"warnings": false
},
"sourceMap": false
}),
Mangle = false 将保留 class 个名称。 angular cli 中缺少 webpack 选项是 atm 的一个大讨论。
您也可以像这样设置排除项:
mangle: {
except: ['foozah']
}
注意:弹出后,您可以从 angular-cli.json 中删除弹出的 true 以再次执行或 serve/build 正常。
"project": {
"name": "test",
"ejected": true //remove
},
mangle中的选项:
"mangle":{
"keep_names" : true
}
保持 class 个名称不变。
根据 Andres M 的回答,您可以通过直接修改控制 Webpack 设置的 Angular 文件来禁用 ng eject
的修改:node_modules/@angular-devkit/build-angular/src/angular-cli-files/models/webpack-configs/common.js
请注意,每当 @angular-devkit/build-angular
更新时,这将被覆盖,并且不受 Angular 或 NPM 的支持(并且可能会杀死你的 cat/cause 一场核大决战,不要说我没有警告过你!)
我通过将 uglifyOptions
更改为 uglifyOptions: Object.assign(uglifyOptions, {mangle: false})
来完全禁用重整。
作为参考,这是我修改后的 common.js
文件
中的相关部分
...
new UglifyJSPlugin({
sourceMap: buildOptions.sourceMap,
parallel: true,
cache: true,
uglifyOptions: Object.assign(uglifyOptions, {"mangle": false})
}),
...
angular 8 使用简洁。
这是我对 angular builder 的配置:
module.exports = cfg => {
const options = cfg.optimization.minimizer[cfg.optimization.minimizer.length - 1].options.terserOptions;
options.keep_classnames = true;
return cfg;
};
并将 terget 更改为 es6
Angular cli 构建器支持 NG_BUILD_MANGLE
、NG_BUILD_MINIFY
、NG_BUILD_BEAUTIFY
节点环境参数(已在版本 8 中检查)。
你可以在 运行 npm 脚本时按以下方式设置它们:
env NG_BUILD_MANGLE=false NG_BUILD_MINIFY=false NG_BUILD_BEAUTIFY=true ng build --prod
这将导致未缩小的输出,但仍会应用 tree shaking 和其他优化(与仅关闭优化相比)。
添加到 yantrab 对 angular 8.2+ 的回答
在angular.json
建设者:@angular-builders/custom-webpack:browser
选项:
"customWebpackConfig": {
"path": "./extra-webpack.config.js",
"mergeStrategies": {
"externals": "replace"
}
},
额外-webpack.config.js:
module.exports = config => {
config.optimization.minimizer.filter (({constructor: {name}}) => name === 'TerserPlugin')
.forEach (terser => {
terser.options.terserOptions.keep_classnames = true;
});
return config;
};
然后根据此处讨论的浏览器列表禁用差异加载的目标 es5 或 es2015:https://github.com/just-jeb/angular-builders/issues/144#issuecomment-568890065
可以通过执行以下操作来避免混淆特定符号:
- 使用
NG_BUILD_MANGLE=false $NG build --prod ...
方法告诉 angular 避免对名称进行任何修改。
- 使用 ngx-build-plus 将部分 webpack 配置与 angular 使用的配置合并。使用 terser 插件执行 mangling,但请确保将您不希望被 mangled 的保留名称列表传递给它。
ng add ngx-build-plus
您可以使用的 webpack.partial.js 类型示例是:
const terser = require('terser-webpack-plugin');
module.exports = {
optimization: {
minimizer: [
new terser.TerserPlugin({
terserOptions: {
compress: false,
mangle: {
reserved: [
"MyClassName1", ...
]
}
}
})
]
}
}
(n.b。确保你也有 运行 npm install --save-dev webpack
!)
然后修改您的构建命令,使其成为以下形式:
NG_BUILD_MANGLE=false ng build --prod ... --extra-webpack-config webpack.partial.js -o
这两件事结合起来告诉 angular 构建过程避免重整,并让您配置的 TerserPlugin 实例在稍后阶段进行重整,同时尊重 类 您希望保持未重整.
对于 Angular 9-12,其他一些答案不再有效。
与 类似,我们不想担心维护 @angular-devkit/build-angular
的修改版本,所以我改为使用 ngx-build-plus
作为我们的构建器以引入一个简单的插件到覆盖 Terser 配置的构建过程。这适用于 Angular 9-11。
我创建了一个名为 build-plugin.js
:
的新文件
exports.default = {
pre: function () {
},
config: function (cfg) {
// Override Angular's internal configuration of Terser to preserve class names.
// This won't work if you build multiple (differential) client bundles, so make sure you only target es5 builds in tsconfig.json.
// See https://github.com/just-jeb/angular-builders/issues/144#issuecomment-576424615
cfg.optimization.minimizer.forEach(function (it) {
if (it.constructor.name === 'TerserPlugin') {
it.options.terserOptions["keep_fnames"] = true;
it.options.terserOptions["keep_classnames"] = true;
}
});
return cfg;
},
post: function () {
}
};
然后更新了项目的angular.json
:
{
"projects": {
"my-project": {
"architect": {
"build": {
"builder": "ngx-build-plus:browser",
"options": {
"plugin": "~build-plugin.js",
...
}
}
}
}
}
...
}
在 Angular 12 中,他们为大多数项目更改了代码优化器 from TerserPlugin
to JavaScriptOptimizerPlugin
。因此,只需更新 build-plugin.js
以包含它的覆盖:
if (it.constructor.name === 'TerserPlugin') {
it.options.terserOptions["keep_fnames"] = true;
it.options.terserOptions["keep_classnames"] = true;
} else if (it.constructor.name === 'JavaScriptOptimizerPlugin') {
it.options.keepNames = true;
}
对于应用程序,我们需要保持 class 名称不缩小,因为我们使用
var className = myObject.constructor.name;
export class myObject{ ... }
当我们运行
ng 构建 -- pro
class 名称被缩小为随机名称。
Angular cli 在内部使用 webpack 和 uglify。一种解决方案是通过导出 webpack 配置来更改 uglify 中的选项。你可以通过 运行 ng eject 和 ng eject --prod
查看 webpack 文件new UglifyJsPlugin({
"mangle": false,
"compress": {
"screw_ie8": true,
"warnings": false
},
"sourceMap": false
}),
Mangle = false 将保留 class 个名称。 angular cli 中缺少 webpack 选项是 atm 的一个大讨论。
您也可以像这样设置排除项:
mangle: {
except: ['foozah']
}
注意:弹出后,您可以从 angular-cli.json 中删除弹出的 true 以再次执行或 serve/build 正常。
"project": {
"name": "test",
"ejected": true //remove
},
mangle中的选项:
"mangle":{
"keep_names" : true
}
保持 class 个名称不变。
根据 Andres M 的回答,您可以通过直接修改控制 Webpack 设置的 Angular 文件来禁用 ng eject
的修改:node_modules/@angular-devkit/build-angular/src/angular-cli-files/models/webpack-configs/common.js
请注意,每当 @angular-devkit/build-angular
更新时,这将被覆盖,并且不受 Angular 或 NPM 的支持(并且可能会杀死你的 cat/cause 一场核大决战,不要说我没有警告过你!)
我通过将 uglifyOptions
更改为 uglifyOptions: Object.assign(uglifyOptions, {mangle: false})
来完全禁用重整。
作为参考,这是我修改后的 common.js
文件
...
new UglifyJSPlugin({
sourceMap: buildOptions.sourceMap,
parallel: true,
cache: true,
uglifyOptions: Object.assign(uglifyOptions, {"mangle": false})
}),
...
angular 8 使用简洁。
这是我对 angular builder 的配置:
module.exports = cfg => {
const options = cfg.optimization.minimizer[cfg.optimization.minimizer.length - 1].options.terserOptions;
options.keep_classnames = true;
return cfg;
};
并将 terget 更改为 es6
Angular cli 构建器支持 NG_BUILD_MANGLE
、NG_BUILD_MINIFY
、NG_BUILD_BEAUTIFY
节点环境参数(已在版本 8 中检查)。
你可以在 运行 npm 脚本时按以下方式设置它们:
env NG_BUILD_MANGLE=false NG_BUILD_MINIFY=false NG_BUILD_BEAUTIFY=true ng build --prod
这将导致未缩小的输出,但仍会应用 tree shaking 和其他优化(与仅关闭优化相比)。
在angular.json
建设者:@angular-builders/custom-webpack:browser
选项:
"customWebpackConfig": {
"path": "./extra-webpack.config.js",
"mergeStrategies": {
"externals": "replace"
}
},
额外-webpack.config.js:
module.exports = config => {
config.optimization.minimizer.filter (({constructor: {name}}) => name === 'TerserPlugin')
.forEach (terser => {
terser.options.terserOptions.keep_classnames = true;
});
return config;
};
然后根据此处讨论的浏览器列表禁用差异加载的目标 es5 或 es2015:https://github.com/just-jeb/angular-builders/issues/144#issuecomment-568890065
可以通过执行以下操作来避免混淆特定符号:
- 使用
NG_BUILD_MANGLE=false $NG build --prod ...
方法告诉 angular 避免对名称进行任何修改。 - 使用 ngx-build-plus 将部分 webpack 配置与 angular 使用的配置合并。使用 terser 插件执行 mangling,但请确保将您不希望被 mangled 的保留名称列表传递给它。
ng add ngx-build-plus
您可以使用的 webpack.partial.js 类型示例是:
const terser = require('terser-webpack-plugin');
module.exports = {
optimization: {
minimizer: [
new terser.TerserPlugin({
terserOptions: {
compress: false,
mangle: {
reserved: [
"MyClassName1", ...
]
}
}
})
]
}
}
(n.b。确保你也有 运行 npm install --save-dev webpack
!)
然后修改您的构建命令,使其成为以下形式:
NG_BUILD_MANGLE=false ng build --prod ... --extra-webpack-config webpack.partial.js -o
这两件事结合起来告诉 angular 构建过程避免重整,并让您配置的 TerserPlugin 实例在稍后阶段进行重整,同时尊重 类 您希望保持未重整.
对于 Angular 9-12,其他一些答案不再有效。
与 @angular-devkit/build-angular
的修改版本,所以我改为使用 ngx-build-plus
作为我们的构建器以引入一个简单的插件到覆盖 Terser 配置的构建过程。这适用于 Angular 9-11。
我创建了一个名为 build-plugin.js
:
exports.default = {
pre: function () {
},
config: function (cfg) {
// Override Angular's internal configuration of Terser to preserve class names.
// This won't work if you build multiple (differential) client bundles, so make sure you only target es5 builds in tsconfig.json.
// See https://github.com/just-jeb/angular-builders/issues/144#issuecomment-576424615
cfg.optimization.minimizer.forEach(function (it) {
if (it.constructor.name === 'TerserPlugin') {
it.options.terserOptions["keep_fnames"] = true;
it.options.terserOptions["keep_classnames"] = true;
}
});
return cfg;
},
post: function () {
}
};
然后更新了项目的angular.json
:
{
"projects": {
"my-project": {
"architect": {
"build": {
"builder": "ngx-build-plus:browser",
"options": {
"plugin": "~build-plugin.js",
...
}
}
}
}
}
...
}
在 Angular 12 中,他们为大多数项目更改了代码优化器 from TerserPlugin
to JavaScriptOptimizerPlugin
。因此,只需更新 build-plugin.js
以包含它的覆盖:
if (it.constructor.name === 'TerserPlugin') {
it.options.terserOptions["keep_fnames"] = true;
it.options.terserOptions["keep_classnames"] = true;
} else if (it.constructor.name === 'JavaScriptOptimizerPlugin') {
it.options.keepNames = true;
}