Webpack 5:如何使用编写为 ES 模块的自定义加载器

问题描述 投票:0回答:1

我如何告诉 Webpack 它应该将我的加载器视为 ES 模块而不是 CommonJS?

我的目标是写一个使用ES Module语法的Loader(

export default...
)

演示(不工作):https://stackblitz.com/edit/webpack-webpack-js-org-7gmdc8?file=webpack.config.js

显然 Webpack 正在尝试将模块加载为 CommonJS。如果您查看 loadLoader,条件

loader.type === "module"
失败,因为
loader.type
undefined
.


// webpack.conf.js:
const path = require('path');

module.exports = {
  mode: 'development',
  entry: './src/app.js',
  output: {
    filename: 'app.js',
    path: path.resolve(__dirname, 'dist'),
    clean: true,
  },

  module: {
    rules: [
      {
        test: /\.js$/,
        use: ['my-loader'],
      },
    ],
  },

  resolveLoader: {
    alias: {
      // WEBPACK IS TRYING TO LOAD THIS AS COMMONJS... WHY???
      'my-loader':
        '/home/projects/webpack-webpack-js-org-7gmdc8/my-loader/main.mjs',
    },
  },
};

示例堆栈跟踪:

ERROR in ./index.js
Module build failed (from ../my-webpack-loader-esm/dist/index.bundle.mjs):
Error [ERR_REQUIRE_ESM]: require() of ES Module /workspaces/webpack-loader-lab/my-webpack-loader-esm/dist/index.bundle.mjs not supported.
Instead change the require of /workspaces/webpack-loader-lab/my-webpack-loader-esm/dist/index.bundle.mjs to a dynamic import() which is available in all CommonJS modules.
    at loadLoader (/workspaces/webpack-loader-lab/the-client/node_modules/loader-runner/lib/loadLoader.js:23:17)
node.js webpack es6-modules commonjs webpack-5
1个回答
0
投票

由于未合并 PR,它目前不可能开箱即用,但我设法为它开发了一个解决方法插件。

首先,我查看了

loadLoader
从哪里获取数据。它来自LoaderRunner.js,webpack正在使用中间对象并向上导航我发现以下代码的调用堆栈:

try {
    hooks.beforeLoaders.call(this.loaders, this, loaderContext);
} catch (err) {
    processResult(err);
    return;
}

这告诉我可以通过钩子更改中间对象,并通过在 webpack 代码中搜索

beforeLoaders
我能够找到为此目的调整的示例插件,结果如下:

import NormalModule from 'webpack/lib/NormalModule.js'

const pluginName = 'MjsLoaderPlugin'
export default class MjsLoaderPlugin {
    apply(compiler) {
        compiler.hooks.compilation.tap(pluginName, compilation => {
            NormalModule.getCompilationHooks(compilation).beforeLoaders.tap(
                pluginName,
                (loaders, normalModule) => {
                    /*
                    loader = {
                        loader: 'F:\\<blah blah>\\webpack-loaders\\my-module-loader.mjs',
                        options: 'name=value',
                        ident: undefined
                    }
                    */

                    for(let loader of loaders) {
                        if(loader.loader.endsWith(".mjs")) {
                            loader.type = 'module'
                        }
                    }
                }
            )
        })
    }
}

也不确定是否相关,这是我的加载程序文件夹的配置部分,告诉 webpack 它可以自动搜索此文件夹中的 mjs 加载程序


import { dirname, resolve } from 'path'
import { fileURLToPath } from 'url'
const __dirname = dirname(fileURLToPath(import.meta.url))

export default {
    resolveLoader: {
        modules: [
            'node_modules',
            resolve(__dirname, 'tools/webpack-loaders')
        ],
        extensions: ['.js', '.mjs']
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.