修改编译后文件的Webpack插件

11

我正在编写一个Webpack插件,它应该用Webpack生成的CSS文件列表来替换JS代码的一部分。想象一下这段JS代码:

ReactWebComponent.create(<App />, 'react-web-component', { injectReactWebComponent: true });

我希望用其他内容代替 injectReactWebComponent: true 部分。

injectReactWebComponent: '<link href="static/css/main.cacbacc7.css" rel="stylesheet">'

虽然那个链接标签是由Webpack生成的文件。

我(有点能用)的代码如下:

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;

看到我所做的那行

child._value = child._value.replace(...)

我直截了当地重写源代码。

但是这对我来说似乎不太对。看起来我正在转换的代码已经被生成,不应再进行转换。 我也很确定我正在破坏源映射。

因此,我想知道,达成我的目标的合适方法是什么?

我猜转换部分应该使用一个loader,但是加载器不知道生成的文件名,对吗?

任何帮助将不胜感激!

2个回答

8

看起来这种事情足够简单,可以由加载器处理,其中有多个(有些比其他人更好):

https://www.npmjs.com/package/string-replace-loader

https://www.npmjs.com/package/regexp-replace-loader

https://www.npmjs.com/package/replace-loader

如果你想自己编写插件来实现这个功能(我刚刚经历了一个比正则表达式替换更复杂的过程),那么我能够从基本上这三个页面中拼凑出我的解决方案:

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


1
看起来加载器在 webpack 之前进行转换。有没有一种方法可以在之后进行转换? - musikele
@musikele 是的,有的,请访问 https://github.com/artembatura/modify-source-webpack-plugin。 - Nick Steele

0
我知道这个问题很旧,但是我需要做类似的事情(我需要修改Quasar 1.x的client-entry.js文件,以便将Quasar应用程序转换为其他人的JavaScript中可调用的库,即我必须停止应用程序自动加载,并且没有Quasar设置可以实现此功能,但是,我只需要在.quasar/client-entry.js中用我的包装函数替换start())。
由于我和作者都只需要在编译后修改webpack文件,并且这个页面是人们搜索如何做类似事情的一个突出结果,而且我使用的是Vue,他们使用的是React,所以我在这里发布了我是如何解决这个问题的,以供作者可能受益以及其他人。
注意:Quasar 1.x使用webpack 4,Quasar 2.x使用webpack 5。我在两个版本的webpack(4和5)上都尝试了这个插件,效果非常好!

https://github.com/artembatura/modify-source-webpack-plugin

这个插件的readme.md文件包含了你使用它所需的一切。它甚至带有concat和replace辅助函数!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接