问题
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!
回答1:
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
来源:https://stackoverflow.com/questions/45644590/webpack-plugin-to-modify-files-after-compilation