英文:
How to solve " [ERR_REQUIRE_ESM]: require() of ES Module" for Webpack case?
问题
I tried to import the w3c-html-validator but got the error
> Error [ERR_REQUIRE_ESM]: require() of ES Module D:(...)\node_m
> odules\w3c-html-validator\node_modules\chalk\source\index.js from
> D:(...)\node_modules\w3c-html-validator\dist\w3c-html-validator.umd.cjs
> not supported.
Looks like this problem is with chalk, the dependency of w3c-html-validator.
I am using the Webpack with webpack-node-externals.
Thank to it, export
/import
keywords are available even though the output is the CommonJS and indented to be executed by plain Node.js. It should be the specific solution for this case, not just "add type: module
to your package.json
".
If possible, I want to avoid the adding of type: module
to the package.json because it could cause other errors. Currently, I have about 30 dependencies (see the appendix) and neither of them requires type: module
.
Appendix
Webpack setup
import Webpack from "webpack";
import Path from "path";
import NodeExternalsPlugin from "webpack-node-externals";
import ForkTypeScriptCheckerWebpackPlugin from "fork-ts-checker-webpack-plugin";
import ESLintPlugin from "eslint-webpack-plugin";
import type { ArbitraryObject } from "@yamato-daiwa/es-extensions";
export default function generateConfiguration(
_environment: ArbitraryObject, commandArguments: ArbitraryObject
): Webpack.Configuration {
const SOURCE_CODE_ROOT_DIRECTORY_ABSOLUTE_PATH: string = Path.resolve(__dirname, "Source");
const __IS_DEVELOPMENT_BUILDING_MODE__: boolean = commandArguments.mode === "development";
const __IS_PRODUCTION_BUILDING_MODE__: boolean = commandArguments.mode === "production";
return {
target: "node",
context: SOURCE_CODE_ROOT_DIRECTORY_ABSOLUTE_PATH,
entry: { EntryPoint: "./EntryPoint.ts" },
output: {
path: __dirname,
filename: "[name].js",
library: {
type: "commonjs"
}
},
/* [ Theory ] Valid non-undefined values are only "development", "production" and "none". */
mode: __IS_DEVELOPMENT_BUILDING_MODE__ ? "development" : "production",
watch: __IS_DEVELOPMENT_BUILDING_MODE__,
optimization: {
emitOnErrors: __IS_DEVELOPMENT_BUILDING_MODE__,
minimize: __IS_PRODUCTION_BUILDING_MODE__
},
node: {
__dirname: false
},
devtool: false,
externals: [
NodeExternalsPlugin({
allowlist: [ "rev-hash" ]
})
],
module: {
rules: [
{
test: /\.ts$/u,
loader: "ts-loader",
options: {
/* [ Theory ] 'ForkTypeScriptCheckerWebpackPlugin' will execute the type checking. */
transpileOnly: true
}
}
]
},
resolve: {
extensions: [ ".ts", ".js" ],
alias: { /* ... */ }
},
plugins: [
new Webpack.DefinePlugin({
__IS_DEVELOPMENT_BUILDING_MODE__,
__IS_PRODUCTION_BUILDING_MODE__
}),
new ForkTypeScriptCheckerWebpackPlugin({
typescript: {
/* [ Theory ] The default value is 'context', but the 'tsconfig.json' is 1 level above 'context'. */
configFile: Path.resolve(__dirname, "tsconfig.json")
}
}),
new ESLintPlugin({
extensions: [ "js", "ts" ],
failOnWarning: __IS_PRODUCTION_BUILDING_MODE__
})
]
};
}
Current dependencies
{
"dependencies": {
"@typescript-eslint/eslint-plugin": "5.57.0",
"@typescript-eslint/parser": "5.57.0",
"@vue/compiler-sfc": "3.2.47",
"@webdiscus/pug-loader": "2.10.4",
"@yamato-daiwa/es-extensions": 1.6.9,
"@yamato-daiwa/es-extensions-nodejs": "1.6.0-alpha.9",
"@yamato-daiwa/style_guides": "0.0.47",
"access-sniff": "3.2.0",
"autoprefixer": "10.4.14",
"browser-sync": "2.27.11",
"cheerio": "1.0.0-rc.1",
"css-loader": "6.7.3",
"cssnano": "5.1.14",
"eslint": "8.37.0",
"eslint-plugin-import": "2.27.5",
"eslint-plugin-node": "11.1.0",
"eslint-webpack-plugin": "4.0.0",
"fork-ts-checker-webpack-plugin": "7.3.0",
"glob": "7.2.0",
"gulp": "4.0.2",
"gulp-data": "1.3.1",
"gulp-debug": "4.0.0",
"gulp-html-prettify": "0.0.1",
"gulp-if": "3.0.0",
"gulp-imagemin": "7.1.0",
"gulp-intercept": "0.1.0",
"gulp-plumber": "1.2.1"
<details>
<summary>英文:</summary>
I tried to import the [w3c-html-validator][1] but got the error
> Error [ERR_REQUIRE_ESM]: require() of ES Module D:\(...)\node_m
> odules\w3c-html-validator\node_modules\chalk\source\index.js from
> D:\(...)\node_modules\w3c-html-validator\dist\w3c-html-validator.umd.cjs
> not supported.
Looks like this problem is with [chalk][2], the dependency of **w3c-html-validator**.
I am using the Webpack with [webpack-node-externals][3].
Thank to it, `export`/`import` keywords are available even though the output is the CommonJS and indented to be executed by plain Node.js. It should be the specific solution for this case, not just "add `type: module` to your `package.json`".
If possible, I want to avoid the adding of `type: module` to the **package.json** because it could cause other errors. Currently, I have about 30 dependencies (see the appendix) and neither of them requires `type: module`.
## Appendix
### Webpack setup
```typescript
import Webpack from "webpack";
import Path from "path";
import NodeExternalsPlugin from "webpack-node-externals";
import ForkTypeScriptCheckerWebpackPlugin from "fork-ts-checker-webpack-plugin";
import ESLintPlugin from "eslint-webpack-plugin";
import type { ArbitraryObject } from "@yamato-daiwa/es-extensions";
export default function generateConfiguration(
_environment: ArbitraryObject, commandArguments: ArbitraryObject
): Webpack.Configuration {
const SOURCE_CODE_ROOT_DIRECTORY_ABSOLUTE_PATH: string = Path.resolve(__dirname, "Source");
const __IS_DEVELOPMENT_BUILDING_MODE__: boolean = commandArguments.mode === "development";
const __IS_PRODUCTION_BUILDING_MODE__: boolean = commandArguments.mode === "production";
return {
target: "node",
context: SOURCE_CODE_ROOT_DIRECTORY_ABSOLUTE_PATH,
entry: { EntryPoint: "./EntryPoint.ts" },
output: {
path: __dirname,
filename: "[name].js",
library: {
type: "commonjs"
}
},
/* [ Theory ] Valid non-undefined values are only "development", "production" and "none". */
mode: __IS_DEVELOPMENT_BUILDING_MODE__ ? "development" : "production",
watch: __IS_DEVELOPMENT_BUILDING_MODE__,
optimization: {
emitOnErrors: __IS_DEVELOPMENT_BUILDING_MODE__,
minimize: __IS_PRODUCTION_BUILDING_MODE__
},
node: {
__dirname: false
},
devtool: false,
externals: [
NodeExternalsPlugin({
allowlist: [ "rev-hash" ]
})
],
module: {
rules: [
{
test: /\.ts$/u,
loader: "ts-loader",
options: {
/* [ Theory ] 'ForkTypeScriptCheckerWebpackPlugin' will execute the type checking. */
transpileOnly: true
}
}
]
},
resolve: {
extensions: [ ".ts", ".js" ],
alias: { /* ... */ }
},
plugins: [
new Webpack.DefinePlugin({
__IS_DEVELOPMENT_BUILDING_MODE__,
__IS_PRODUCTION_BUILDING_MODE__
}),
new ForkTypeScriptCheckerWebpackPlugin({
typescript: {
/* [ Theory ] The default value is 'context', but the 'tsconfig.json' is 1 level above 'context'. */
configFile: Path.resolve(__dirname, "tsconfig.json")
}
}),
new ESLintPlugin({
extensions: [ "js", "ts" ],
failOnWarning: __IS_PRODUCTION_BUILDING_MODE__
})
]
};
}
Current dependencies
{
"dependencies": {
"@typescript-eslint/eslint-plugin": "5.57.0",
"@typescript-eslint/parser": "5.57.0",
"@vue/compiler-sfc": "3.2.47",
"@webdiscus/pug-loader": "2.10.4",
"@yamato-daiwa/es-extensions": 1.6.9,
"@yamato-daiwa/es-extensions-nodejs": "1.6.0-alpha.9",
"@yamato-daiwa/style_guides": "0.0.47",
"access-sniff": "3.2.0",
"autoprefixer": "10.4.14",
"browser-sync": "2.27.11",
"cheerio": "1.0.0-rc.1",
"css-loader": "6.7.3",
"cssnano": "5.1.14",
"eslint": "8.37.0",
"eslint-plugin-import": "2.27.5",
"eslint-plugin-node": "11.1.0",
"eslint-webpack-plugin": "4.0.0",
"fork-ts-checker-webpack-plugin": "7.3.0",
"glob": "7.2.0",
"gulp": "4.0.2",
"gulp-data": "1.3.1",
"gulp-debug": "4.0.0",
"gulp-html-prettify": "0.0.1",
"gulp-if": "3.0.0",
"gulp-imagemin": "7.1.0",
"gulp-intercept": "0.1.0",
"gulp-plumber": "1.2.1",
"gulp-postcss": "9.0.1",
"gulp-pug": "5.0.0",
"gulp-sourcemaps": "3.0.0",
"gulp-stylus": "2.7.1",
"imagemin-pngquant": "9.0.2",
"json5-loader": "4.0.1",
"minimatch": "5.1.1",
"node-notifier": "10.0.1",
"prettier": "2.8.7",
"pug-lint": "2.6.0",
"pug-plain-loader": "1.1.0",
"rev-hash": "4.0.0",
"stlint": "1.0.65",
"stream-combiner2": "1.1.1",
"style-loader": "3.3.1",
"stylus-loader": "7.1.0",
"ts-loader": "9.4.2",
"vinyl": "2.2.1",
"vue": "3.2.47",
"vue-loader": "17.0.1",
"vue-style-loader": "4.1.3",
"vue-tsc": "1.2.0",
"w3c-html-validator": "1.3.3",
"webpack": "5.76.2",
"webpack-node-externals": "3.0.0",
"webpack-stream": "7.0.0",
"worker-loader": "3.0.8",
"yaml-loader": "0.8.0"
},
"devDependencies": {
"@types/browser-sync": "2.26.3",
"@types/cheerio": "0.22.31",
"@types/cssnano": "5.0.0",
"@types/glob": "7.2.0",
"@types/gulp": "4.0.10",
"@types/gulp-debug": "2.0.32",
"@types/gulp-html-prettify": "0.0.2",
"@types/gulp-if": "0.0.34",
"@types/gulp-imagemin": "8.0.1",
"@types/gulp-intercept": "0.1.1",
"@types/gulp-plumber": "0.0.33",
"@types/gulp-postcss": "8.0.2",
"@types/gulp-sourcemaps": "0.0.35",
"@types/gulp-stylus": "2.7.4",
"@types/node": "18.13.0",
"@types/node-notifier": "8.0.2",
"@types/pug": "2.0.6",
"@types/webpack-node-externals": "2.5.3",
"@types/webpack-stream": "3.2.12",
"ts-node": "10.9.1",
"typescript": "5.0.3",
"webpack-cli": "5.0.1"
}
}
答案1
得分: 1
As you noted, the problem is that w3c-html-validator
使用了 chalk
的 ESM 版本。基本上,w3c-html-validator
的维护者错误地构建了 UMD/CJS 变体,试图 require
其自身的一个 ESM 依赖 🙃。
简单解决方案:将你的 w3c-html-validator
版本降级到 v0.8.1
,该版本使用了 chalk
的 CommonJS 版本。
Babel 解决方案:在你的 webpack 构建中添加 babel-loader
,将 chalk
依赖进行转译,将 import/export
转换为 require/module.exports
,即 ESM 到 CJS。
你的 babel 配置应该类似于这样(如果你的 devDependencies 中没有的话,添加 @babel/preset-env
):
{
"presets": [
["@babel/preset-env", {
"modules": "commonjs"
}]
]
}
你的更新后的 webpack 配置应该包含类似于这样的内容:
module: {
rules: [
{
test: /\.(t|j)sx?$/,
include: filename => {
return /node_modules\/chalk/.test(filename)
},
use: ['babel-loader']
}
]
}
英文:
As you noted, the problem is that w3c-html-validator
is using an ESM version of chalk
. Basically, the maintainer of w3c-html-validator
has built the UMD/CJS variant incorrectly by trying to require
one of its own ESM dependencies 🙃.
Simple solution: Downgrade your version of w3c-html-validator
to v0.8.1
which uses a CommonJS version of chalk
.
Babel solution: Add babel-loader
to your webpack build and transpile the chalk
dependency to convert the import/export
to require/module.exports
, i.e. ESM to CJS.
Your babel config should look something like this (add @babel/preset-env
if not already in your devDependencies):
{
"presets": [
["@babel/preset-env", {
"modules": "commonjs"
}]
]
}
Your updated webpack config should include something like this:
module: {
rules: [
{
test: /\.(t|j)sx?$/,
include: filename => {
return /node_modules\/chalk/.test(filename)
},
use: ['babel-loader']
}
]
}
答案2
得分: 0
If the problem is your use of webpack-node-externals
you might have luck with code like below.
Note that this solution relies on you knowing which modules are native dependencies (which should not take long to figure out.)
You might update the beginning of your config like this:
return {
target: "node",
externals: ['sharp', 'another-native-node-dep'], // Add your native dependency names to the array and remove my examples
context: SOURCE_CODE_ROOT_DIRECTORY_ABSOLUTE_PATH,
entry: { EntryPoint: "./EntryPoint.ts" },
英文:
If the problem is your use of webpack-node-externals
you might have luck with code like below.
Note that this solution relies on you knowing which modules are native dependencies (which should not take long to figure out.)
You might update the beginning of your config like this:
return {
target: "node",
externals: ['sharp', 'another-native-node-dep'], // Add your native dependency names to the array and remove my examples
context: SOURCE_CODE_ROOT_DIRECTORY_ABSOLUTE_PATH,
entry: { EntryPoint: "./EntryPoint.ts" },
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论