如何将自定义内容转换为 webpack 中的 javascript 模块?

How can I transform custom content into a javascript module in webpack?

我有一个自定义格式,我想将其转换为 Javascript,以便可以将其导入到我的 React 应用程序中。这个改造的细节已经解决了,不重要了。

为了实现这一点,我编写了一个执行转换的自定义加载程序(实际上,将执行转换的可执行文件打包)。这部分看起来效果不错!

var child_process = require('child_process');

module.exports = function(source) {
    const callback = this.async();

    const exepath = "..\xml-converter\xml-converter\bin\debug\xml-converter.exe"

    const child = child_process.exec(exepath, { shell: false }, function(error, stdout, stderr) {
        return callback(error, stdout);
    });

    child.stdin.write(source);
    child.stdin.end();
}

我已经将它添加到 webpack 中,我知道它正在被使用。

//...
module: {
    rules: [
        //...other rules...
        {
            test: /\.xml$/,
            use: [
                {  //more on this later
                    loader: 'babel-loader',
                    options: {
                        presets: ['@babel/preset-env']
                    }
                },
                {
                    loader: path.resolve(__dirname, 'room_loader.js')
                }
            ]
        }
    ]
}

然后,我尝试在代码中使用这个加载器:

import myAwesomeData from './myData.xml'

console.log(myAwesomeData.aPropertyThatIsDefinitelyThere)
console.log(myAwesomeData)

这输出:

undefined
/static/media/myData.05d816d8.xml

它不是给我我的 javascript,而是将其视为图像或其他东西,然后返回 javascript 来构建 URL。如果我手动加载提供的 URL,我会得到预期的源代码:

export let myAwesomeData = {
    aPropertyThatIsDefinitelyThere: "whatever..."
}

然而,这显然不是我想要的

我尝试将 babel 加载器链接到等式中(见上文),虽然它起作用了(正确转译代码),但它没有解决核心问题。

我想做的事情可行吗?如果可以,怎么做?

所以,我过度简化了我的问题陈述,结果我的问题不是我想的那样。

我正在使用 create-react-app,但这并不能按照我需要的方式自定义 Webpack(加载自定义加载器),所以我添加了 react-app-rewired。然后我将其添加到我的自定义文件中:

module.exports = function override(config, env) {
    config.module.rules.push({
        test: /\.xml$/,
        use: [
        {
            loader: path.resolve(__dirname, 'room_loader.js')
        }]
    });

    return config;
};

然而,仔细检查预定义的规则(最容易通过弹出来完成,但您可以在其他地方找到它们)表明这是正确的。放置它们的正确位置是在第三条规则中,它有一个以通用 "we don't know how to handle this, so we'll treat it like an image" 加载器结尾的子规则列表。

因此你真正想做的是:

module.exports = function override(config, env) {
    var rules = config.module.rules[2].oneOf;

    var position = rules.length - 2;

    rules.splice(position, 0, {
        test: /\.xml$/,
        use: [
        {
            loader: path.resolve(__dirname, 'room_loader.js')
        }]
    });

    return config;
};

效果很好,比我想象的要容易得多。