【问题标题】:Angular-cli : How to ignore class names from being minifiedAngular-cli:如何忽略类名被缩小
【发布时间】:2017-10-24 22:42:47
【问题描述】:

对于应用程序,我们需要保持类名不被缩小,因为我们使用

var className = myObject.constructor.name;
export class myObject{ ... }

当我们运行时

ng build -- pro

类名被缩小为一个随机名称。

【问题讨论】:

    标签: angular typescript angular-cli bundling-and-minification


    【解决方案1】:

    对于 Angular 9-12,其他一些答案不再适用。

    类似于Rob's answer,我们不想担心维护@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;
    }
    

    【讨论】:

      【解决方案2】:

      通过执行以下操作可以避免损坏特定符号:

      • 使用 NG_BUILD_MANGLE=false $NG build --prod ... 方法告诉 Angular 避免对名称进行任何修改。
      • 使用 ngx-build-plus 将部分 webpack 配置与 angular 使用的配置合并。使用 terser 插件执行重整,但请确保将您不想被重整的名称的保留列表传递给它。
      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", ...
                  ]
                }
              }
            })
          ]
        }
      }
      
      

      (注意,请确保您也运行过npm install --save-dev webpack!)

      然后修改您的构建命令,使其具有以下形式:

      NG_BUILD_MANGLE=false ng build --prod ... --extra-webpack-config webpack.partial.js -o
      

      这两件事结合起来告诉 Angular 构建过程避免重整,并让您配置的 TerserPlugin 实例在稍后阶段进行重整,同时尊重您希望保持未重整的类。

      【讨论】:

      • 如何设置这个 NG_BUILD_MANGLE=false。
      • NG_BUILD_MANGLE=false ng build --prod
      【解决方案3】:

      使用angular-builders添加到 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

      【讨论】:

        【解决方案4】:

        Angular cli builder 支持NG_BUILD_MANGLENG_BUILD_MINIFYNG_BUILD_BEAUTIFY 节点环境参数(在版本 8 中签入)。

        您可以在运行 npm 脚本时通过以下方式设置它们: env NG_BUILD_MANGLE=false NG_BUILD_MINIFY=false NG_BUILD_BEAUTIFY=true ng build --prod

        这将导致输出未缩小,但仍会应用摇树和其他优化(与仅关闭优化相比)。

        【讨论】:

        • 我如何设置这个环境,你能详细解释一下
        • NG_BUILD_MANGLE = false 仍在重命名类名
        【解决方案5】:

        angular 8 使用 terser。

        这是我对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

        【讨论】:

        • 感谢您的解决方案,但我面临的一个问题是 - 在遵循您提到的所有步骤之后,但现在我面临一个问题,例如在 like 之前附加类名 - 考虑一个类是 AbLogin 然后之后生产构建类名称变为 ab_login_AbLogin
        • 就我而言,terser 插件不一定是正确的
        • 这在 angular 8 到 8.1 中为我们工作。似乎在 angular 8.2 cli 或更高版本(包括 angular 9+)中,如果启用了差异加载,cli 将忽略 terserOptions。我花了很长时间才弄明白。还有一种更好的方法来设置 terserOptions,因为上面的代码只修改了一个最小化器,而实际上有多个。请参阅此问题的解决方案:github.com/just-jeb/angular-builders/issues/144
        【解决方案6】:

        根据 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 支持(并且可能会杀死你的猫/导致核世界末日,不要说我没有警告你!)

        我通过将 uglifyOptions 更改为 uglifyOptions: Object.assign(uglifyOptions, {mangle: false}) 完全禁用了 mangling。

        作为参考,这是我修改后的common.js 文件中的相关部分

        ...
        new UglifyJSPlugin({
          sourceMap: buildOptions.sourceMap,
          parallel: true,
          cache: true,
          uglifyOptions: Object.assign(uglifyOptions, {"mangle": false})
        }),
        ...
        

        【讨论】:

          【解决方案7】:

          mangle 中的选项:

          "mangle":{
             "keep_names" : true
          }
          

          保持类名不变。

          【讨论】:

          • 不应该是 keep_fnames: true,
          【解决方案8】:

          Angular cli 在内部使用 webpack 和 uglify。一种解决方案是通过导出 webpack 配置来更改 uglify 中的选项。你可以通过运行 ng injection 和 ngject --prod 来查看 webpack 文件

          new UglifyJsPlugin({
                "mangle": false,
                "compress": {
                  "screw_ie8": true,
                  "warnings": false
                },
                "sourceMap": false
              }),
          

          Mangle = false 将保留类名。 angular cli 中缺少 webpack 的选项是一大讨论 atm。

          您也可以像这样设置排除项:

          mangle: {
              except: ['foozah']
            }
          

          注意:弹出后,您可以从 angular-cli.json 中删除弹出的 true 以再次执行此操作或正常服务/构建。

          "project": {
              "name": "test",
              "ejected": true //remove
            },
          

          【讨论】:

          • 编辑构建后,使用 'npm start' 或 'npm run build'。
          • 请记住一点,一旦我们使用了ng eject,我们就不能再使用 angular-cli 的好东西了。
          • ngject 在最新版本的 angular-cli 中不起作用,还有其他方法可以在 prod build 中配置 mangle 吗?
          猜你喜欢
          • 2021-06-18
          • 2017-09-19
          • 2023-03-21
          • 1970-01-01
          • 2018-08-04
          • 1970-01-01
          • 2014-01-01
          • 1970-01-01
          • 2012-12-22
          相关资源
          最近更新 更多