Webpack:如何为 "webpack" 创建一个加载器,它需要一个依赖数组?

Webpack: How can I create a loader for "webpack" which takes an array of dependencies?

比如我在我的项目中使用AMD定义,并且在项目构建中使用"webpack"。是否可以创建一些加载程序以数组格式接收依赖项?

define(
    [
        'mySuperLoader![./path/dependency-1, ./path/dependency-2, ...]'
    ],
    function() {
        // ... some logic here
    }
)

项目示例:gitHub

我认为您不应该为此使用加载器。为什么不直接写:

require("./path/dependency-1");
require("./path/dependency-2");
require("./path/dependency-3");

它完成同样的事情,表现力更强,不需要额外的 code/loader/hack/configuration。

如果您仍然不满意,您可能会对 webpack contexts 感兴趣,它允许您要求大量与给定过滤器匹配的文件。所以,如果你写

require("./template/" + name + ".jade");

webpack 包括所有可以通过这个表达式访问的模块,而无需访问父目录。和写

基本一样
require("./table.jade");
require("./table-row.jade");
require("./directory/folder.jade")

您也可以像这样手动创建上下文

var myRequire = require.context(
    "./template",   // search inside this directory
    false,         // false excludes sub-directories
    /\.jade$/      // use this regex to filter files
);

var table = myRequire("./table.jade");

如果你想将 load-plugin 的行为移植到 webpack,你需要这样做:

1。创建自定义解析器

这是因为 mySuperLoader![./path/dependency-1, ./path/dependency-2, ...] 没有指向 单个 文件。当 webpack 尝试加载文件时,它首先:

  • 解析文件路径
  • 加载文件内容
  • 匹配并解析所有加载器
  • 将文件内容传递给加载程序链

由于 [./path/dependency-1, ./path/dependency-2, ...] 不是正确的文件路径,因此还有一些工作要做。它甚至不是一个合适的 JSON.

所以,我们的第一个目标是把它变成mySuperLoader!some/random/file?["./path/dependency-1", "./path/dependency-2", ...]。这通常通过创建自定义解析器来完成:

// webpack.config.js
var customResolverPlugin = {
    apply: function (resolver) {
        resolver.plugin("resolve", function (context, request) {
            const matchLoadRequest = /^\[(.+)]$/.exec(request.path);

            if (matchLoadRequest) {
                request.query = '?' + JSON.stringify(
                    matchLoadRequest[1]
                    .split(", ")
                );
                request.path = __filename;
            }
        });
    }
};

module.exports = {
    ...
    plugins: [
        {
            apply: function (compiler) {
                compiler.resolvers.normal.apply(customResolverPlugin);
            }
        }
    ]
};

通知request.path = __filename;?我们只需要给 webpack 一个现有的文件,这样它就不会抛出错误。无论如何,我们将生成所有内容。可能不是最优雅的解决方案,但它确实有效。

2。创建我们自己的 load-loader(是的!)

// loadLoader.js
const path = require("path");

function loadLoader() {
    return JSON.parse(this.request.match(/\?(.+?)$/)[1])
        .map(module =>
            `exports['${path.basename(module, '.js')}'] = require('${module}');`
        )
        .join('\n');
}

module.exports = loadLoader;

这个加载器解析我们用自定义解析器重写的请求查询,并创建一个如下所示的 CommonJS 模块

exports['dependency-1'] = require('path/to/dependency-1');
exports['dependency-2'] = require('path/to/dependency-2');

3。别名我们自己的 load-loader

// webpack.config.js

    ...
    resolveLoader: {
        alias: {
            load: require.resolve('./loadLoader.js')
        }
    },

4。配置 root

由于/path/to/dependency-1是root-relative,我们需要将root添加到webpack config

// webpack.config.js
resolve: {
    root: '/absolute/path/to/root' // usually just __dirname
},

这既不是一个漂亮的解决方案也不是一个理想的解决方案,但在您移植模块之前应该可以作为权宜之计。