How to create a External Plugin in webpack5?

445 Views Asked by At

I tried to create an external plugin that can ask webpack not bundle things. Because threads-plugin don't accept external setting of webpack, it can only use plugin to external things.

I tried my best to make this:

const ModuleFilenameHelpers = require('webpack/lib/ModuleFilenameHelpers');
const ExternalModule = require('webpack/lib/ExternalModule');

class ExternalsPlugin {
  constructor(options) {
    this.options = options;
  }

  apply(compiler) {
    const options = this.options;
    compiler.hooks.normalModuleFactory.tap('ExternalsPlugin', function (nmf) {
      nmf.hooks.resolve.tapAsync(
        {
          name: 'NormalModuleFactory',
          stage: 100,
        },
        function (module, callback) {
          if (ModuleFilenameHelpers.matchObject(options, module.createData.resource)) {
            const { context, dependencies } = module;
            const newModule = new ExternalModule(module.request, options.type || compiler.options.output.libraryTarget);
            callback(null, newModule);
          }
          callback(null);
        },
      );
    });
  }
}

But it rise

callback is not a function
TypeError: callback is not a function
    at /Users/linonetwo/Desktop/repo/TiddlyGit-Desktop/node_modules/webpack/lib/util/AsyncQueue.js:352:5
    at Hook.eval [as callAsync] (eval at create (/Users/linonetwo/Desktop/repo/TiddlyGit-Desktop/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:6:1)
    at AsyncQueue._handleResult (/Users/linonetwo/Desktop/repo/TiddlyGit-Desktop/node_modules/webpack/lib/util/AsyncQueue.js:322:21)
    at /Users/linonetwo/Desktop/repo/TiddlyGit-Desktop/node_modules/webpack/lib/util/AsyncQueue.js:305:11
    at /Users/linonetwo/Desktop/repo/TiddlyGit-Desktop/node_modules/webpack/lib/Compilation.js:1780:5
    at /Users/linonetwo/Desktop/repo/TiddlyGit-Desktop/node_modules/webpack/lib/NormalModuleFactory.js:761:5
    at eval (eval at create (/Users/linonetwo/Desktop/repo/TiddlyGit-Desktop/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:13:1)
    at /Users/linonetwo/Desktop/repo/TiddlyGit-Desktop/node_modules/webpack/lib/NormalModuleFactory.js:322:16
    at Hook.eval [as callAsync] (eval at create (/Users/linonetwo/Desktop/repo/TiddlyGit-Desktop/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:6:1)
    at /Users/linonetwo/Desktop/repo/TiddlyGit-Desktop/node_modules/webpack/lib/NormalModuleFactory.js:304:31
    at Hook.eval [as callAsync] (eval at create (/Users/linonetwo/Desktop/repo/TiddlyGit-Desktop/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:6:1)
    at /Users/linonetwo/Desktop/repo/TiddlyGit-Desktop/node_modules/webpack/lib/NormalModuleFactory.js:288:30
    at eval (eval at create (/Users/linonetwo/Desktop/repo/TiddlyGit-Desktop/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:16:1)
    at /Users/linonetwo/Desktop/repo/TiddlyGit-Desktop/webpack.plugins.js:39:11
    at _next0 (eval at create (/Users/linonetwo/Desktop/repo/TiddlyGit-Desktop/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:8:1)
    at eval (eval at create (/Users/linonetwo/Desktop/repo/TiddlyGit-Desktop/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:30:1)

So does someone know how to properly declare some module to be external using a plugin?

1

There are 1 best solutions below

0
On

This is the answer:

const ModuleFilenameHelpers = require('webpack/lib/ModuleFilenameHelpers');
const ExternalModule = require('webpack/lib/ExternalModule');

class ExternalsPlugin {
  constructor(options) {
    this.options = options;
  }

  apply(compiler) {
    const options = this.options;
    compiler.hooks.normalModuleFactory.tap('ExternalsPlugin', function (nmf) {
      nmf.hooks.resolve.tapAsync(
        {
          name: 'NormalModuleFactory',
          stage: 100,
        },
        function (module, callback) {
          if (ModuleFilenameHelpers.matchObject(options, module.createData.resource)) {
            const { context, dependencies } = module;
            const newModule = new ExternalModule(module.request, options.type || compiler.options.output.libraryTarget, module.createData.userRequest);
            callback(null, newModule);
          } else {
            callback(null);
          }
        },
      );
    });
  }
}

I forget to add else around second callback(null)

 else {
            callback(null);
          }

So callback call two times, second time it throws error.