I am writing a Webpack plugin that should replace a part of the JS code with a list of Webpack's generated CSS files. Imaging this JS code:
ReactWebComponent.create(<App />, 'react-web-component', { injectReactWebComponent: true });
I want to replace the injectReactWebComponent: true
part with
injectReactWebComponent: '<link href="static/css/main.cacbacc7.css" rel="stylesheet">'
While that link tag is a file generated by Webpack.
My (kind of working) code for this goes as follows:
ReactWebComponent.prototype.apply = function(compiler) {
compiler.plugin('emit', function(compilation, callback) {
const cssFiles = Object.keys(compilation.assets)
.filter(fileName => /\.css$/.test(fileName));
const jsFiles = Object.keys(compilation.assets)
.filter(fileName => /\.js$/.test(fileName));
const cssLinkTagsAsString = cssFiles
.map(fileName => `<link href="${fileName}" rel="stylesheet">`)
.join('');
jsFiles.forEach(fileName => {
compilation.assets[fileName].children.forEach(child => {
if (child._value) {
child._value = child._value.replace(/injectReactWebComponent\s*:\s*true/g, `injectReactWebComponent: \'${cssLinkTagsAsString}\'`);
}
});
});
callback();
});
};
module.exports = ReactWebComponent;
See the line where I do
child._value = child._value.replace(...)
I am bluntly rewriting the sources.
But this does not seem right for me. It seems the code I am transforming has already been generated and not ought to be transformed anymore. I am also pretty sure I am breaking the source maps with this.
So I am wondering, what would be an appropriate way to achieve what I am doing?
I am guessing for the transformation part I should use a loader
, but then loaders do not know about the generated file names, or do they?
Any help would be appreciated!
Disclaimer: CopyWebpackPlugin is a third-party package maintained by community members, it potentially does not have the same support, security policy or license as webpack, and it is not maintained by webpack. Copies individual files or entire directories, which already exist, to the build directory.
Loaders work at the individual file level during or before the bundle is generated. Plugins: Plugins work at bundle or chunk level and usually work at the end of the bundle generation process. Plugins can also modify how the bundles themselves are created.
Webpack is an aggressive and powerful module bundler for JavaScript applications. It packages all the modules in your application into one or more bundles (often, just one) and serves it to the browser.
A webpack plugin is a JavaScript object that has an apply method. This apply method is called by the webpack compiler, giving access to the entire compilation lifecycle.
It appears this sort of thing is simple enough to be handled by loaders, of which there are multiple (some better than others):
https://www.npmjs.com/package/string-replace-loader
https://www.npmjs.com/package/regexp-replace-loader
https://www.npmjs.com/package/replace-loader
If you want to go about making your own plugin to do this (I just went through the process to do something a bit more sophisticated than just regex replacement), I was able to piece my solution together from basically these three pages:
https://github.com/webpack/webpack/blob/master/lib/BannerPlugin.js
https://webpack.js.org/api/plugins/compilation/#optimize-chunk-assets-chunks-chunk-async
https://github.com/webpack/webpack-sources
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