I'm writing a Webpack plugin. During module resolution, this plugin should dynamically add a specific loader for some modules, but not for all.
My idea right now is to tap into normal-module-factory
's after-resolve
event. There, I could modify the array data.loaders
. Some debugging showed me that this array contains objects of the form { loader: string, options: object | undefined }
.
I couldn't find any documentation on modifying per-module loaders on the fly. So I'm wondering:
loaders
entries contain an additional property ident
, looking like this: 'ref--0-0'
. When should I set this property, and using what value?I'm not sure whether it's the best solution, but this code appears to work:
class MyPlugin {
apply(compiler) {
compiler.plugin('normal-module-factory', normalModuleFactory => {
normalModuleFactory.plugin('after-resolve', (data, callback) => {
data.loaders.push({
loader: ..., // Path to loader
options: {}
});
callback(null, data);
});
});
}
}
module.exports = MyPlugin;
Regarding the extra ident
property: Webpack needs to be able to compare loader options. By default, it does this by calling JSON.stringify()
on the options object, then comparing the resulting strings. By adding an ident
property, you can explicitly specify a string representation of the options object. For details, see https://stackoverflow.com/a/49006233/52041.
I was attempting to solve a similar problem, and wanted to add a loader only for specific files identified elsewhere in a plugin. My solution goes as follows:
loader.js
module.exports = function loader(content) {
return mySpecialTransformation(content);
};
plugin.js
const path = require('path');
class MyPluginName {
apply(compiler) {
compiler.hooks.compilation.tap('MyPluginName', compilation => {
compilation.hooks.normalModuleLoader.tap('MyPluginName', (loaderContext, module) => {
if (myModuleCondition(module)) {
module.loaders.unshift({
loader: path.resolve(__dirname, 'loader.js'), // Path to loader
options: {}
});
}
});
});
}
}
Note that I've used unshift rather than push to add the loader - I'm still in the development stage so I could be wrong, but my current understanding is that I would want my loader to run after all 'standard' loaders which may well be transpiling typescript, etc. I believe that loaders are then applied from right to left. Depending on what you're doing this may not be important.
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