Webpack插件:如何动态地将加载器添加到模块?

时间:2018-02-26 15:58:05

标签: javascript webpack

我正在编写一个Webpack插件。在模块解析期间,此插件应为某些模块动态添加特定加载器,但不是全部。

我现在的想法是利用normal-module-factory的{​​{1}}事件。在那里,我可以修改数组after-resolve。一些调试向我显示该数组包含data.loaders形式的对象。

我找不到任何关于动态修改每个模块加载器的文档。所以我想知道:

  • 这是正确的方法吗?
  • 某些(但不是全部)现有{ loader: string, options: object | undefined }条目包含其他属性loaders,如下所示:ident。我应该何时设置此属性,并使用什么值?

2 个答案:

答案 0 :(得分:2)

我不确定它是否是最佳解决方案,但此代码似乎有效:

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;

关于额外的ident属性:Webpack需要能够比较加载器选项。默认情况下,它通过调用选项对象上的JSON.stringify(),然后比较生成的字符串来完成此操作。通过添加ident属性,您可以显式指定选项对象的字符串表示形式。有关详细信息,请参阅https://stackoverflow.com/a/49006233/52041

答案 1 :(得分:0)

我正在尝试解决类似的问题,并且只想为插件中其他位置标识的特定文件添加加载程序。我的解决方案如下:

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: {}
          });
        }
      });
    });
  }
}

请注意,我使用unshift而不是推送来添加加载器-我仍处于开发阶段,因此我可能会错了,但是我目前的理解是,我希望加载器在所有“标准”条件下运行装载程序很可能是打字稿等。我相信,然后从右到左应用装载程序。根据您的操作,这可能并不重要。