You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Webpack打包产物含require语句,ESM环境Node.js运行报错求助

问题描述

我有一个仅使用ESM规范的TypeScript项目,通过Webpack将代码打包为单个JavaScript文件。执行node ./dist/index.js时出现错误:

const external_minimist_namespaceObject = require("minimist");
                                          ^

ReferenceError: require is not defined in ES module scope, you can use import instead
This file is being treated as an ES module because it has a '.js' file extension and 'package.json' contains "type": "module". To treat it as a CommonJS script, rename it to use the '.cjs' file extension.

我的package.json中已配置"type": "module",Webpack运行脚本为:"dist": "node --loader ts-node/esm node_modules/webpack-cli/bin/cli.js -c ./webpack.config.ts"。

以下是我的webpack.config.ts配置:

import path from 'node:path';
import fs from 'node:fs/promises';
import { fileURLToPath } from 'node:url';

import webpack from 'webpack';
import nodeExternals from 'webpack-node-externals';
import TsconfigPathsPlugin from 'tsconfig-paths-webpack-plugin';
import WebpackShellPluginNext from 'webpack-shell-plugin-next';

const packageJsonData = await fs.readFile('package.json', 'utf-8');
const packageJsonObject = JSON.parse(packageJsonData);
const version = packageJsonObject.version;

const __dirname = path.dirname(fileURLToPath(import.meta.url));

const configuration: webpack.Configuration = {
    context: __dirname,
    mode: 'production',
    target: 'node',
    entry: './src/index.ts',
    optimization: { minimize: false },
    externals: [nodeExternals({ modulesDir: path.join(__dirname, 'node_modules') })],
    experiments: { outputModule: true },
    module: {
        rules: [
            {
                test: /\.ts$/,
                use: [
                    {
                        loader: 'ts-loader',
                        options: { configFile: 'tsconfig.build.json' },
                    },
                ],
                exclude: /node_modules/,
            },
        ],
    },
    plugins: [
        new WebpackShellPluginNext({
            onBuildStart: {
                scripts: ['rimraf dist'],
                blocking: true,
            },
            safe: true,
        }),
        new webpack.DefinePlugin({
            __PACKAGE_VERSION__: JSON.stringify(version),
        }),
    ],
    resolve: {
        extensions: ['.ts'],
        plugins: [
            new TsconfigPathsPlugin({
                configFile: './tsconfig.base.json',
                extensions: ['.ts'],
            }),
        ],
    },
    output: {
        filename: 'index.js',
        path: path.resolve(__dirname, 'dist'),
        library: { type: 'module' },
        chunkFormat: 'module',
    },
};

export default configuration;

关键配置文件tsconfig.base.json内容如下:

{
    "extends": "./tsconfig.paths.json",
    "compilerOptions": {
        "target": "ES2018",
        "module": "ESNext",
        "moduleResolution": "bundler",
        "noEmit": true,
        "baseUrl": "./",
        "allowJs": false,
        "skipLibCheck": true,
        "strict": true,
        "forceConsistentCasingInFileNames": true,
        "esModuleInterop": true,
        "resolveJsonModule": true,
        "isolatedModules": true,
        "incremental": true,
        "removeComments": true,
        "allowUnreachableCode": false,
        "allowUnusedLabels": false,
        "alwaysStrict": true,
        "noFallthroughCasesInSwitch": true,
        "noImplicitAny": true,
        "noImplicitOverride": true,
        "noImplicitReturns": true,
        "noImplicitThis": true,
        "noPropertyAccessFromIndexSignature": true,
        "noUncheckedIndexedAccess": true,
        "noUnusedLocals": true,
        "noUnusedParameters": true,
        "typeRoots": ["./node_modules/@types", "./@types"]
    }
}

Webpack打包成功,但无法用Node.js运行产物文件,请问为何打包产物中是require语句而非import,导致无法在ESM环境正常运行?

解决方案

问题出在webpack-node-externals插件上——它默认会把外部依赖以CommonJS的require语法输出,哪怕你配置了ESM的打包模式。

要解决这个问题,按以下步骤调整配置:

  • 修改webpack.config.ts中的externals配置:给nodeExternals添加importType: 'module'参数,强制它生成ESM风格的导入语句:
externals: [
  nodeExternals({
    modulesDir: path.join(__dirname, 'node_modules'),
    importType: 'module',
    allowlist: [] // 若有需要打包进产物的外部依赖,在此添加,否则留空
  })
],
  • 检查tsconfig.build.json配置:确保该文件的module和moduleResolution与tsconfig.base.json保持一致,即"module": "ESNext"、"moduleResolution": "bundler",避免ts-loader编译出CommonJS代码。

  • 确认Webpack的ESM输出配置:你已经开启了experiments.outputModule: true,这是Webpack输出ESM模块的关键开关,保持该配置即可。

修改后重新打包,产物中的外部依赖会替换为import语句,即可在ESM环境正常运行。

内容的提问来源于stack exchange,提问作者Tal Rofe

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 08:23:20