Webpack 在 minifying/uglifying 具有继承的 ES6 代码时删除类名
Webpack's removes classnames when minifying/uglifying ES6 code with inheritance
Webpack 删除 classnames when minifying/uglifying ES6 code with inheritance:
有 MVCE 代码,我们尝试 minify/uglify:
Class Child:
const ParentClass = require('parent');
class Child extends ParentClass{
constructor(){
super();
}
}
module.exports = Child;
index.js 调用 Child
class:
const Child = require('./classes_so/child');
let child = new Child();
console.log(child.constructor.name);
模块 Parent 里面 node_modules
:
class Parent {
constructor() {
if (this.constructor.name === 'Parent'){
throw new TypeError("Parent class is abstract - cant be instance");
}
}
}
module.exports = Parent;
整个输出我会 post 到问题的结尾,这里我只想 post 我认为导致错误行为的相关行(原始输出的第 33-37 行):
n.exports = class extends r {
constructor() {
super();
}
};
为什么这里缺少 class名称:class extends r
?我希望该值会被破坏但会存在,我可以将其视为错误吗?我尝试使用 keep_classnames
标志,但它保留了不可接受的原始 class 名称。
我们正在使用:
- Webpack:3.11.0(尝试使用 4,行为相同)
- uglifyjs-webpack-plugin: 1.2.4(尝试使用不同的插件)
- NodeJS:v6.9.1 和 v8.9.1(相同的输出)
- 演示问题的完整项目:webpack-uglify-inheritence
更新 1:
- 在 uglifyjs-webpack-plugin repository
打开一个问题
我们的webpack.config.js
:
const webpack = require('webpack');
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
const path = require('path');
const fs = require('fs');
const nodeModules = {};
const localDependencies = ['.bin'];
fs.readdirSync('node_modules')
.filter(function (x) {
return localDependencies.indexOf(x) === -1;
})
.forEach(function (mod) {
nodeModules[mod] = 'commonjs ' + mod;
});
try {
module.exports = {
target: 'node',
node: {
console: false,
global: false,
process: false,
Buffer: false,
__filename: true,
__dirname: true
},
entry: './index_so.js',
output: {
path: path.join(__dirname, 'build'),
filename: 'index.js'
},
externals: nodeModules,
plugins: [
new webpack.IgnorePlugin(/\.(css|less)$/),
new webpack.BannerPlugin({
banner: 'require("source-map-support").install();',
raw: true,
entryOnly: false
})
],
devtool: 'sourcemap',
module: {
loaders: [
{test: /\.json$/, loader: "json-loader"}
]
},
plugins: [
new UglifyJsPlugin({
uglifyOptions: {
compress: {
warnings: false
},
keep_classnames: false,
mangle: true,
output: {
beautify: true
}
}
})
]
};
}
catch (e) {
console.error(e);
}
上面示例中的整个 minified/uglified 代码:
!function(n) {
var t = {};
function e(r) {
if (t[r]) return t[r].exports;
var o = t[r] = {
i: r,
l: !1,
exports: {}
};
return n[r].call(o.exports, o, o.exports, e), o.l = !0, o.exports;
}
e.m = n, e.c = t, e.d = function(n, t, r) {
e.o(n, t) || Object.defineProperty(n, t, {
configurable: !1,
enumerable: !0,
get: r
});
}, e.n = function(n) {
var t = n && n.__esModule ? function() {
return n.default;
} : function() {
return n;
};
return e.d(t, "a", t), t;
}, e.o = function(n, t) {
return Object.prototype.hasOwnProperty.call(n, t);
}, e.p = "", e(e.s = 0);
}([ function(n, t, e) {
let r = new (e(1))();
console.log(r.constructor.name);
}, function(n, t, e) {
const r = e(2);
n.exports = class extends r {
constructor() {
super();
}
};
}, function(n, t) {
n.exports = require("parent");
} ]);
给定设置中的问题不在 webpack 或 uglify 的代码中,而是在这部分代码中:
class Parent {
constructor() {
if (this.constructor.name === 'Parent') {
throw new TypeError("Parent class is abstract - cant be instance");
}
}
}
module.exports = Parent;
this.constructor.name === 'Parent'
中继 class
/function
名称,以测试 Parent
是否被直接实例化。
与其传递一个可能导致各种问题的名称,不如测试构造函数是否等于 class。
class Parent {
constructor() {
if (this.constructor === Parent) {
throw new TypeError("Parent class is abstract - cant be instance");
}
}
}
module.exports = Parent;
试试我的库 typescript-class-helpers
import { CLASS } from 'typescript-class-helpers/browser';
@CLASS.NAME('Parent')
class Parent {
constructor() {
if (CLASS.getNameFromObject(child) === 'Parent'){
throw new TypeError("Parent class is abstract - cant be instance");
}
}
}
@CLASS.NAME('Child')
class Child extends ParentClass{
constructor(){
super();
}
}
let child = new Child();
console.log(CLASS.getNameFromObject(child)); // Child
有了这个,你可以缩小你的 类 名字,一切都会好起来的。
Webpack 删除 classnames when minifying/uglifying ES6 code with inheritance:
有 MVCE 代码,我们尝试 minify/uglify:
Class Child:
const ParentClass = require('parent');
class Child extends ParentClass{
constructor(){
super();
}
}
module.exports = Child;
index.js 调用 Child
class:
const Child = require('./classes_so/child');
let child = new Child();
console.log(child.constructor.name);
模块 Parent 里面 node_modules
:
class Parent {
constructor() {
if (this.constructor.name === 'Parent'){
throw new TypeError("Parent class is abstract - cant be instance");
}
}
}
module.exports = Parent;
整个输出我会 post 到问题的结尾,这里我只想 post 我认为导致错误行为的相关行(原始输出的第 33-37 行):
n.exports = class extends r {
constructor() {
super();
}
};
为什么这里缺少 class名称:class extends r
?我希望该值会被破坏但会存在,我可以将其视为错误吗?我尝试使用 keep_classnames
标志,但它保留了不可接受的原始 class 名称。
我们正在使用:
- Webpack:3.11.0(尝试使用 4,行为相同)
- uglifyjs-webpack-plugin: 1.2.4(尝试使用不同的插件)
- NodeJS:v6.9.1 和 v8.9.1(相同的输出)
- 演示问题的完整项目:webpack-uglify-inheritence
更新 1:
- 在 uglifyjs-webpack-plugin repository 打开一个问题
我们的webpack.config.js
:
const webpack = require('webpack');
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
const path = require('path');
const fs = require('fs');
const nodeModules = {};
const localDependencies = ['.bin'];
fs.readdirSync('node_modules')
.filter(function (x) {
return localDependencies.indexOf(x) === -1;
})
.forEach(function (mod) {
nodeModules[mod] = 'commonjs ' + mod;
});
try {
module.exports = {
target: 'node',
node: {
console: false,
global: false,
process: false,
Buffer: false,
__filename: true,
__dirname: true
},
entry: './index_so.js',
output: {
path: path.join(__dirname, 'build'),
filename: 'index.js'
},
externals: nodeModules,
plugins: [
new webpack.IgnorePlugin(/\.(css|less)$/),
new webpack.BannerPlugin({
banner: 'require("source-map-support").install();',
raw: true,
entryOnly: false
})
],
devtool: 'sourcemap',
module: {
loaders: [
{test: /\.json$/, loader: "json-loader"}
]
},
plugins: [
new UglifyJsPlugin({
uglifyOptions: {
compress: {
warnings: false
},
keep_classnames: false,
mangle: true,
output: {
beautify: true
}
}
})
]
};
}
catch (e) {
console.error(e);
}
上面示例中的整个 minified/uglified 代码:
!function(n) {
var t = {};
function e(r) {
if (t[r]) return t[r].exports;
var o = t[r] = {
i: r,
l: !1,
exports: {}
};
return n[r].call(o.exports, o, o.exports, e), o.l = !0, o.exports;
}
e.m = n, e.c = t, e.d = function(n, t, r) {
e.o(n, t) || Object.defineProperty(n, t, {
configurable: !1,
enumerable: !0,
get: r
});
}, e.n = function(n) {
var t = n && n.__esModule ? function() {
return n.default;
} : function() {
return n;
};
return e.d(t, "a", t), t;
}, e.o = function(n, t) {
return Object.prototype.hasOwnProperty.call(n, t);
}, e.p = "", e(e.s = 0);
}([ function(n, t, e) {
let r = new (e(1))();
console.log(r.constructor.name);
}, function(n, t, e) {
const r = e(2);
n.exports = class extends r {
constructor() {
super();
}
};
}, function(n, t) {
n.exports = require("parent");
} ]);
给定设置中的问题不在 webpack 或 uglify 的代码中,而是在这部分代码中:
class Parent {
constructor() {
if (this.constructor.name === 'Parent') {
throw new TypeError("Parent class is abstract - cant be instance");
}
}
}
module.exports = Parent;
this.constructor.name === 'Parent'
中继 class
/function
名称,以测试 Parent
是否被直接实例化。
与其传递一个可能导致各种问题的名称,不如测试构造函数是否等于 class。
class Parent {
constructor() {
if (this.constructor === Parent) {
throw new TypeError("Parent class is abstract - cant be instance");
}
}
}
module.exports = Parent;
试试我的库 typescript-class-helpers
import { CLASS } from 'typescript-class-helpers/browser';
@CLASS.NAME('Parent')
class Parent {
constructor() {
if (CLASS.getNameFromObject(child) === 'Parent'){
throw new TypeError("Parent class is abstract - cant be instance");
}
}
}
@CLASS.NAME('Child')
class Child extends ParentClass{
constructor(){
super();
}
}
let child = new Child();
console.log(CLASS.getNameFromObject(child)); // Child
有了这个,你可以缩小你的 类 名字,一切都会好起来的。