使用Uglify的keep_fnames在生产模式下使用Webpack后重复的类名

时间:2018-04-24 10:59:45

标签: webpack uglifyjs

我正在开发一个依赖Function.prototype.name的库(在父实例上设置快捷方式)。

class FooSection {}
class BarSection {}

class Page {
  constructor(sections) {
    for (let SectionClass of sections) {
      this[SectionClass.name] = new SectionClass(this);
    }
  }
}

let page = new Page([
  FooSection,
  BarSection
]);

这一切都很好用,直到从Webpack的优化开始进行修改。默认情况下会破坏函数名称,导致类及其name属性被缩短。通常有用,不在这里。所以我去了并将适当的配置传递给了Webpack:

// ...
optimization: {
  minimizer: [
    new UglifyJsPlugin( {
                          uglifyOptions: {
                            keep_fnames: true
                          }
                        } )
  ]
}

根据文档,这应该保留我的函数名称。令人惊讶的是,发生的是名称​​重复,因此Page突然变为Page_Page注意:此代码块是由我编写的,但这大致是什么输出看起来像):

class FooSection_FooSection{}
class BarSection_BarSection{}
class Page_Page{
  constructor(t) {
    for(let s of t){this[s.name]=new s(this)}
  }
}
let p=new Page_Page([FooSection_FooSection,BarSection_BarSection])

单独使用UglifyJS这是不可重现的,因此它必须位于工具链内部(webpack - > uglifyjs-webpack-plugin - > uglifyjs),但我无法弄清楚在哪里。有没有人经历过这个?

版本如下:

  • webpack:4.6.0
  • uglifyjs-webpack-plugin:1.2.5
  • uglifyjs:3.3.9

更新
根据评论,使用TerserPlugin uglifier似乎也会出现同样的问题。

1 个答案:

答案 0 :(得分:1)

这是一个很老的话题,但是当我偶然发现同一问题并最终找出原因时,我只是把它放在这里作为参考。

此行为是由webpack的ModuleConcatenationPlugin引起的,出于性能原因,该webpack将所有模块移到了全局范围内。这可能会导致名称冲突,因此,webpack会对类进行重命名,并为它们加上文件/模块名称的前缀。

您可以通过在Webpack配置中将concatenateModules设置为false来禁用此行为。

module.exports = {
  //...
  optimization: {
    concatenateModules: false
  }
};

由于这不是一个bug,而您正在编写一个库,因此依靠这种行为可能不是一个好主意。