我有一个TypeScript项目,我使用Webpack将代码捆绑到一个JavaScript文件中。我使用ESM只有。当我尝试通过运行: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"
。我有这个脚本在我的package.json
文件中运行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',
// * https://stackoverflow.com/questions/48673408/should-javascript-npm-packages-be-minified
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成功完成,但我无法使用NodeJS (node ./dist/index.js
)运行分发文件。为什么发行文件包含require
语句而不是import
语句以成功运行ESM
?
解决方法如下:
externals: [
nodeExternals({
modulesDir: path.join(__dirname, 'node_modules'),
importType: (moduleName) => `import ${moduleName}`,
}),
],
这将注入import
语句而不是requires