最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Webpack plugin: How to dynamically add a loader to a module? - Stack Overflow

programmeradmin2浏览0评论

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:

  • Is this the right approach?
  • Some (but not all) existing 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 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:

  • Is this the right approach?
  • Some (but not all) existing loaders entries contain an additional property ident, looking like this: 'ref--0-0'. When should I set this property, and using what value?
Share Improve this question asked Feb 26, 2018 at 15:58 Daniel WolfDaniel Wolf 13.7k15 gold badges64 silver badges86 bronze badges
Add a ment  | 

2 Answers 2

Reset to default 4

I'm not sure whether it's the best solution, but this code appears to work:

class MyPlugin {
  apply(piler) {
    piler.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 pare loader options. By default, it does this by calling JSON.stringify() on the options object, then paring the resulting strings. By adding an ident property, you can explicitly specify a string representation of the options object. For details, see https://stackoverflow./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(piler) {
    piler.hooks.pilation.tap('MyPluginName', pilation => {
      pilation.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.

发布评论

评论列表(0)

  1. 暂无评论