Recently, I started learning how to build webpack plugins. I'm trying to build a plugin that will update my source code.
The rules are simple:
a
s, I have to rename all the variables haha
to hehe
in all modules in the chunk of the said entry point.a
s, I have to rename all the variables haha
to hoho
of all modules in the chunk of the said entry point.This is my code:
a.js
const haha = 'hello';
// will be "const hehe = 'hello';" in the bundle of "aa" entry point
// will be "const hoho = 'hello';" in the bundle of "aaaa" entry point
console.log(haha);
// will be "console.log(hehe);" in the bundle of "aa" entry point
// will be "console.log(hoho);" in the bundle of "aaaa" entry point
export default haha;
// will be "export default hehe;" in the bundle of "aa" entry point
// will be "export default hoho;" in the bundle of "aaaa" entry point
few.js
import haha from 'a'; // will be "import hehe from 'a';" in the bundle
console.log(haha); // will be "console.log(hehe);" in the bundle
lots.js
import haha from 'a'; // will be "import hoho from 'a';" in the bundle
console.log(haha); // will be "console.log(hoho);" in the bundle
webpack.config.js
module.exports = {
mode: 'development',
entry: {
aa: 'few.js',
aaaa: 'lots.js'
},
output: {
filename: '[name].js',
path: path.resolve(__dirname, 'dist')
}
};
I don't know exactly what the proper way to do that.
At the beginning, I thought that my plugin has to register to a specific hook of the parser, check the name of the current entry point and replace the name of the AST node. The problem is that the module a.js
is parsed only once.
The second way I tried is to register to the render
hook of the mainTemplate
and rename variables via a simple regex. I don't like this method since code replacing via regex is extremely difficult (IMO).
What do you think? What is the proper way to that?
Ya right. You can't get entry info in modules. I think you can solve may be in other way not using entry point. As modules are cached once it is loaded, we can make use of inline resource query
a.js
const haha = 'hello';
console.log(haha);
export default haha;
few.js
import haha from './a?change=e'; // will be "import hehe from 'a';" in the bundle
console.log(haha); // will be "console.log(hehe);" in the bundle
lots.js
import haha from './a?change=o'; // will be "import hehe from 'a';" in the bundle
console.log(haha); // will be "console.log(hoho);" in the bundle
custom loader -> transformer.js
module.exports = function(source) {
let queryval = "";
if (this.resourceQuery && this.resourceQuery.indexOf('change')) {
queryval = this.resourceQuery.substr(this.resourceQuery.indexOf("change"+ 1));
// console.log("queryval: ", queryval);
if (queryval) {
const replacedCode = source.replace(/[a]/g, queryval); // this replace every thing but need own logic even default -> def_ult _ is query val :P
console.log("replacedCode: ", replacedCode);
return replacedCode;
}
}
return source;
}
webpack.config.js
const path = require('path');
module.exports = {
mode: 'development',
entry: {
aa: './src/few.js',
aaaa: './src/lots.js'
},
module: {
rules: [
{
test: /\.js$/,
oneOf: [
{
resourceQuery: /change/,
use: [
{
loader: path.resolve('./src/transformer.js'),
options: {
replaceWith: true
}
}
],
},
{
loader: path.resolve('./src/transformer.js'),
}
],
}
]
},
output: {
filename: '[name].js',
path: path.resolve(__dirname, 'dist')
},
optimization: {
runtimeChunk: "single"
}
};
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With