如何编写基于其他模块动态添加模块的Webpack插件?

时间:2017-01-26 08:34:30

标签: webpack webpack-2 webpack-plugin

我在为翻译服务编写Webpack插件时遇到问题。

目标是:

  1. 在编译期间获取所有必需模块的名称(和源代码)。我需要能够扫描包含的源代码以获取特殊的t()函数用法,但我想只扫描那些将包含在bundle中的模块(根据构建配置,它可以是所有项目的子集)模块)。
  2. 根据收集的模块,我想动态创建其他模块(带翻译)并将它们添加到捆绑包中。这些模块需要能够导入自己的依赖项。
  3. 另一个要求是Webpack的代码拆分功能应该与动态创建的模块一起使用(我想将它们提取到单独的文件中 - 例如bundle.[lang].js)。此外,这可能超出了这个问题的范围,我必须使这些翻译块可选(因此您不必加载所有语言,只需加载一个)。

    更多详细信息,请参阅https://github.com/ckeditor/ckeditor5/issues/387

    我一直在尝试多种解决方案,但Webpack 2的文档并不是很有帮助。我可以通过监听模块解析挂钩(before-resolve)来获取所有模块,但我不知道什么时候所有的依赖项都得到解决,我不知道之后是否可以添加更多模块(以及如何这样做 - addEntry好吗,什么时候可以使用?)。

    我还在考虑连接Webpack插件和Webpack加载器(因为我需要的功能非常类似于Webpack's style-loader),但是从插件级别我只能添加加载器的路径,而不是加载器本身,所以我不能将配置对象作为参数传递 - 我错了吗?

    PS。我使用Webpack 2.如果您对这些要求感到陌生,请参阅https://github.com/ckeditor/ckeditor5/issues/387:)。

1 个答案:

答案 0 :(得分:4)

这是一个非常复杂的问题,但我可以展示如何向特定模块添加其他依赖项,就好像那些模块需要这些依赖项一样。这可确保您添加的模块将处于正确的块中,并且如果从模块中删除父模块,也将删除这些模块。

const CommonJsRequireDependency = require("webpack/lib/dependencies/CommonJsRequireDependency")

class MyPlugin {
  apply(compiler) {
    compiler.plugin("compilation", compilation => {
      compilation.plugin("succeed-module", module => {
        // this will be called for every successfully built module, but before it's parsed and
        // its dependencies are built. The built source is available as module._source.source()
        // and you can add additional dependencies like so:
        module.dependencies.push(new CommonJsRequireDependency("my-dependency", null))
      }
    }
  }
}

这只是其中的一部分。您还可能需要编写自己的加载程序来实际生成翻译(您可以用my-dependency替换上面的my-loader!path/to/module以立即调用它)并在创建块之后的某个步骤将它们提取到一个新资产并加载它们,因为它们实际上并不是require d。