我有一个需求:
访问函数的arguments,但是在严格模式下,arguments是禁止访问并且操作的,所以,我,要删除webpack打包出来的代码里的所有use strict。
尝试
项目基于webpack
一开始搜索得到的结果是: 使用webpack的loader,来去除所有use strict
字符串,babel-loader
有一个插件transform-remove-strict-mode
,webpack.config.js的配置如下(记得要安装npm i babel-plugin-transform-remove-strict-mode -S
):
{
module: {
rules: [
{
test: /\.js$/,
use: [
{
loader: 'babel-loader',
query: {
plugins: ["transform-remove-strict-mode"],
}
}
]
}
]
}
}
使用这个插件前use strict 数量
remove-strict.js
):
function removeStrict(code) {
return code.replace(/(\"|\')use strict(\"|\');/gi, '');
}
module.exports = function(source) {
// source 为 compiler 传递给 Loader 的一个文件的原内容
source = removeStrict(source);
return source;
};
然后webpack.config.js配置如下:
resolveLoader: {
// 这个是声明你本地loader位置的地方,因为我没有上传npm包,remove-strict.js放在loaders目录下
modules: [path.join(__dirname, '../loaders/'), 'node_modules']
},
module: {
rules: [
{
test: /\.js$/,
use: [
{
loader: 'babel-loader',
query: {
plugins: ["transform-remove-strict-mode"],
}
},
{
loader: 'remove-strict'
}
]
}
]
}
再打包发现use strict的数量还是有:
解决最后一个use strict:
翻阅webpack源码发现,webpack内置的FunctionModuleTemplatePlugin
会对打包的代码插入use strict,
这个时候我就纳闷,buildInfo.strict是在哪设置成true的,搜node_modules下所有的buildInfo.strict = true;发现2个地方用到:
凭直觉UseStrictPlugin
应该不是原因,所以看HarmonyDetectionParserPlugin
,发现:
查阅资料:
ast.body.some(
statement =>
statement.type === "ImportDeclaration" ||
statement.type === "ExportDefaultDeclaration" ||
statement.type === "ExportNamedDeclaration" ||
statement.type === "ExportAllDeclaration"
)
是babel的一个语法树解析结果,当有一个节点的类型是ImportDeclaration
等类型时,isHarmony就是true。其实他的意思是当采用es6的import或者export语法时,就返回true。于是我试验了一下把import改成require,发现use strict的确都没了,但是我还是想在import模式下去除所有的use strict,于是我掏出了webpack plugin:
class RemoveStrictPlugin {
constructor() {
}
removeStrict(content) {
if (content && content.replace) {
const re = /(\"|\')use strict(\"|\');?/gi;
return content.replace(re, () => {
return '';
});
}
return content;
}
apply(compiler) {
const self = this;
compiler.plugin("compilation", function (compilation) {
compilation.plugin("optimize-chunk-assets", function (chunks, callback) {
let files = [];
chunks.forEach(function (chunk) {
return files.push.apply(files, chunk.files);
});
files.forEach(file => {
let chunkSource = compilation.assets[file];
let source = chunkSource._source;
let children = source.children;
source.children = children.map(item => {
if (typeof item === 'string') {
return self.removeStrict(item);
}
else if (typeof item === 'object' && item._source) {
item._source.value = self.removeStrict(item._source.value);
return item;
}
else {
return item;
}
});
});
callback();
});
});
}
}
module.exports = RemoveStrictPlugin;
webpack.config.js配置:
const RemoveStrictPlugin = require('../plugins/RemoveStrictPlugin');
module.exports = {
// 其他配置...
plugins: [
new RemoveStrictPlugin()
]
};
里面的compilation
能拿到打包后的所有字符串,我做的就是把每个节点里的字符串内容移除use strict替换一下,这下成功移除所有的use strict:
好的,后续上传npm包。
参考资料: