免责声明。提供的实现可能不适合您。您可能需要修改它以使用您的webpack 版本。另外,我的目标是nodejs(不是浏览器),因此我忽略了源映射。
假设你有src/index.js:
const mysql2 = require('whatever');
以及以下软件包:
{
"dependencies": {
"mysql2": "2.3.3",
"webpack": "5.64.2",
"webpack-cli": "4.9.1"
}
}
和webpack.config.js:
const path = require('path');
const RewriteRequirePlugin = require('./rewrite-require-plugin');
module.exports = {
mode: 'development',
target: 'node',
module: {
rules: [
// {test: path.resolve('src/index.js'),
// use: [
// {loader: path.resolve('rewrite-require-loader.js'),
// options: {
// search: "'whatever'",
// replace: JSON.stringify('mysql2'),
// }},
// ]}
],
},
plugins: [
// new RewriteRequirePlugin([
// [path.resolve('src/index.js'),
// "'whatever'",
// JSON.stringify('mysql2')],
// ])
],
stats: {
modulesSpace: Infinity,
groupModulesByPath: false,
}
};
它不会构建。但如果你取消注释插件或加载器,它会。
rewrite-require-loader.js:
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions#escaping
function escapeRegExp(string) {
return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string
}
function processFile(source, search, replace) {
const re = `require\\(${escapeRegExp(search)}\\)`;
return source.replace(
new RegExp(re, 'g'),
`require(${replace})`);
}
module.exports = function(source) {
const options = this.getOptions();
return processFile(source, options.search, options.replace);
};
rewrite-require-plugin.js:
const path = require('path');
const NormalModule = require('webpack/lib/NormalModule');
// https://github.com/webpack/loader-runner/blob/v4.2.0/lib/LoaderRunner.js#L9-L16
function utf8BufferToString(buf) {
var str = buf.toString("utf-8");
if(str.charCodeAt(0) === 0xFEFF) {
return str.substr(1);
} else {
return str;
}
}
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions#escaping
function escapeRegExp(string) {
return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string
}
function processFile(source, search, replace) {
source = Buffer.isBuffer(source) ? utf8BufferToString(source) : source;
const re = `require\\(${escapeRegExp(search)}\\)`;
return source.replace(
new RegExp(re, 'g'),
`require(${replace})`);
}
class RewriteRequirePlugin {
constructor(rewrites) {
this.rewrites = rewrites.map(r => [path.resolve(r[0]), r[1], r[2]]);
}
apply(compiler) {
compiler.hooks.compilation.tap('RewriteRequirePlugin', compilation => {
// https://github.com/webpack/webpack/blob/v5.64.2/lib/schemes/FileUriPlugin.js#L36-L43
const hooks = NormalModule.getCompilationHooks(compilation);
hooks.readResource
.for(undefined)
.tapAsync("FileUriPlugin", (loaderContext, callback) => {
const { resourcePath } = loaderContext;
loaderContext.addDependency(resourcePath);
loaderContext.fs.readFile(resourcePath, (err, data) => {
if (err) return callback(err, data);
callback(
err,
this.rewrites.reduce(
(prev, cur) =>
resourcePath == cur[0]
? processFile(data, cur[1], cur[2])
: data,
data));
});
});
});
}
};
module.exports = RewriteRequirePlugin;