vite
vite copied to clipboard
ESM `.postcssrc.ts` w. `"type": "module"` results in `ERR_REQUIRE_ESM`
Originally reported over here by @ElPrudi (before the issue was fixed in postcss-load-config):
- https://github.com/vitejs/vite/issues/14758
Describe the bug
Upgrading to a version after [email protected] (which added support for ESM postcss.config.ts w. "type": "module" does not resolve the problem in Vite that require() is used to load an ESM postcss.config.ts (or any other variations on the TS config) when in a "type": "module" project:
> vite
[Failed to load PostCSS config: Failed to load PostCSS config (searchPath: /home/projects/vitejs-vite-2gepfr): [Error] Must use import to load ES Module: /home/projects/vitejs-vite-2gepfr/.postcssrc.ts
require() of ES modules is not supported.
require() of /home/projects/vitejs-vite-2gepfr/.postcssrc.ts from /home/projects/vitejs-vite-2gepfr/node_modules/vite/dist/node/chunks/dep-bb8a8339.js is an ES module file as it is a .ts file whose nearest parent package.json contains "type": "module" which defines all .ts files in that package scope as ES modules.
Instead change the requiring code to use import(), or remove "type": "module" from /home/projects/vitejs-vite-2gepfr/package.json.
Error: Must use import to load ES Module: /home/projects/vitejs-vite-2gepfr/.postcssrc.ts
require() of ES modules is not supported.
require() of /home/projects/vitejs-vite-2gepfr/.postcssrc.ts from /home/projects/vitejs-vite-2gepfr/node_modules/vite/dist/node/chunks/dep-bb8a8339.js is an ES module file as it is a .ts file whose nearest parent package.json contains "type": "module" which defines all .ts files in that package scope as ES modules.
Instead change the requiring code to use import(), or remove "type": "module" from /home/projects/vitejs-vite-2gepfr/package.json.
at createErrRequireEsm (/home/projects/vitejs-vite-2gepfr/node_modules/ts-node/dist-raw/node-internal-errors.js:46:15)
at assertScriptCanLoadAsCJSImpl (/home/projects/vitejs-vite-2gepfr/node_modules/ts-node/dist-raw/node-internal-modules-cjs-loader.js:584:11)
at Object.require.extensions.<computed> [as .ts] (/home/projects/vitejs-vite-2gepfr/node_modules/ts-node/src/index.ts:1610:5)
at Module.load (node:internal/modules/cjs/loader:54:13457)
at Function.Module._load (node:internal/modules/cjs/loader:54:10535)
at Module.require (node:internal/modules/cjs/loader:54:13775)
at i (node:internal/modules/cjs/helpers:98:2198)
at eval (/home/projects/vitejs-vite-2gepfr/node_modules/vite/dist/node/chunks/dep-bb8a8339.js:36654:16)
at Object.search (/home/projects/vitejs-vite-2gepfr/node_modules/vite/dist/node/chunks/dep-bb8a8339.js:29044:44)] {
code: 'ERR_REQUIRE_ESM'
}
cc @bluwy
Reproduction
https://stackblitz.com/edit/vitejs-vite-2gepfr?file=package.json
Steps to reproduce
Create a config file called postcss.config.ts (or .postcssrc.ts, as in the reproduction above):
import type { Config } from 'postcss-load-config'
import cssnano from 'cssnano'
export default ({ env }): Config => ({
plugins: [
cssnano({
preset: 'default'
})
]
})
System Info
System:
OS: Linux 5.0 undefined
CPU: (8) x64 Intel(R) Core(TM) i9-9880H CPU @ 2.30GHz
Memory: 0 Bytes / 0 Bytes
Shell: 1.0 - /bin/jsh
Binaries:
Node: 18.18.0 - /usr/local/bin/node
Yarn: 1.22.19 - /usr/local/bin/yarn
npm: 10.2.3 - /usr/local/bin/npm
pnpm: 8.14.0 - /usr/local/bin/pnpm
Used Package Manager
npm
Logs
See logs above
Validations
- [X] Follow our Code of Conduct
- [X] Read the Contributing Guidelines.
- [X] Read the docs.
- [X] Check that there isn't already an issue that reports the same bug to avoid creating a duplicate.
- [X] Make sure this is a Vite issue and not a framework-specific issue. For example, if it's a Vue SFC related bug, it should likely be reported to vuejs/core instead.
- [X] Check that this is a concrete bug. For Q&A open a GitHub Discussion or join our Discord Chat Server.
- [X] The provided reproduction is a minimal reproducible example of the bug.
#15235 would fix this. But it's a breaking change, so it will probably be added in v6. Use .cts extension for now.
@brc-dd thanks!
I tried using postcss.config.cts, but this resulted in a confusing ts-node error which I was unable to find much info on:
[Failed to load PostCSS config: Failed to load PostCSS config (searchPath: /Users/k/p/projec/packages/slide-decks): [TSError] ⨯ Unable to compile TypeScript:
error TS5110: Option 'module' must be set to 'NodeNext' when option 'moduleResolution' is set to 'NodeNext'.
TSError: ⨯ Unable to compile TypeScript:
error TS5110: Option 'module' must be set to 'NodeNext' when option 'moduleResolution' is set to 'NodeNext'.
at createTSError (/Users/k/p/projec/node_modules/ts-node/src/index.ts:859:12)
at reportTSError (/Users/k/p/projec/node_modules/ts-node/src/index.ts:863:19)
at /Users/k/p/projec/node_modules/ts-node/src/index.ts:1379:34
at Object.compile (/Users/k/p/projec/node_modules/ts-node/src/index.ts:1440:28)
at Module.m._compile (/Users/k/p/projec/node_modules/ts-node/src/index.ts:1617:30)
at Module._extensions..js (node:internal/modules/cjs/loader:1435:10)
at Object.require.extensions.<computed> [as .js] (/Users/k/p/projec/node_modules/ts-node/src/index.ts:1621:12)
at Module.load (node:internal/modules/cjs/loader:1207:32)
at Function.Module._load (node:internal/modules/cjs/loader:1023:12)
at Module.require (node:internal/modules/cjs/loader:1235:19)] {
diagnosticCodes: [ 5110 ]
}
fatal error: all goroutines are asleep - deadlock!
goroutine 1 [chan receive]:
github.com/evanw/esbuild/internal/helpers.(*ThreadSafeWaitGroup).Wait(...)
github.com/evanw/esbuild/internal/helpers/waitgroup.go:36
main.runService.func2()
github.com/evanw/esbuild/cmd/esbuild/service.go:114 +0x8c
main.runService(0x1)
github.com/evanw/esbuild/cmd/esbuild/service.go:160 +0x4b4
main.main()
github.com/evanw/esbuild/cmd/esbuild/main.go:240 +0x8d8
goroutine 18 [chan receive]:
main.runService.func1()
github.com/evanw/esbuild/cmd/esbuild/service.go:98 +0x40
created by main.runService
github.com/evanw/esbuild/cmd/esbuild/service.go:97 +0x1a0
goroutine 19 [chan receive]:
main.(*serviceType).sendRequest(0x140001ac060, {0x100866300, 0x140000d3b00})
github.com/evanw/esbuild/cmd/esbuild/service.go:192 +0x11c
main.runService.func3()
github.com/evanw/esbuild/cmd/esbuild/service.go:125 +0x38
created by main.runService
github.com/evanw/esbuild/cmd/esbuild/service.go:122 +0x308
error Command failed with exit code 1.
My tsconfig.json file does indeed use NodeNext for both module and moduleResolution:
{
"$schema": "https://json.schemastore.org/tsconfig",
"extends": "eslint-config-upleveled/tsconfig.base.json",
"compilerOptions": {
"target": "ES2022",
"module": "NodeNext",
"moduleResolution": "NodeNext",
"checkJs": true,
"jsx": "preserve"
},
"include": [
"**/*.ts",
"**/*.tsx",
"**/*.js",
"**/*.jsx",
"**/*.cts",
"**/*.cjs",
"**/*.mjs"
],
"exclude": ["node_modules"]
}
I tried also switching to tsx as suggested by other users having issues with ts-node ("NODE_OPTIONS='--import tsx' vite dev"), but this led to a different confusing error, also thrown by ts-node:
[Failed to load PostCSS config: Failed to load PostCSS config (searchPath: /Users/k/p/projec/packages/slide-decks): [TypeError] Cannot assign to read only property '.mjs' of object '[object Object]'
TypeError: Cannot assign to read only property '.mjs' of object '[object Object]'
at registerExtension (/Users/k/p/projec/node_modules/ts-node/src/index.ts:1607:26)
at registerExtensions (/Users/k/p/projec/node_modules/ts-node/src/index.ts:1579:5)
at Object.register (/Users/k/p/projec/node_modules/ts-node/src/index.ts:600:3)
at file:///Users/k/p/projec/node_modules/vite/dist/node/chunks/dep-94_H5fT6.js:29068:43
at Object.search (file:///Users/k/p/projec/node_modules/vite/dist/node/chunks/dep-94_H5fT6.js:21277:48)]
error Command failed with exit code 1.
Probably ts-node has some issue with nodenext. You can do something like:
// tsconfig.json
{
// ...
"ts-node": {
"transpileOnly": true,
"compilerOptions": {
"module": "ESNext",
"moduleResolution": "Node10"
}
}
}
https://stackblitz.com/edit/vitejs-vite-mbgkvz
Just for added clarity: you can install v5 of postcss-load-config, you can override transitive dependencies to use v5, but Vite still contains postcss-load-config v4 as vendored code. That's why, even after excising ts-node from your codebase, you still get a ts-node error.
IMO just stick with postcss.config.cjs for now. It's just not worth the trouble trying to get ts-node working in a modern environment.
I wonder if Vite v6 could reconsider vendoring postcss-load-config? I definitely wasn't aware until now that installing my own postcss-load-config means I'm writing a "type-safe" config for a completely different version than what's baked into Vite. That is… not ideal!
As an alternative to not vendoring postcss-load-config, would Vite consider re-exporting the PostCSS config type from postcss-load-config? This would have the advantage of allowing us to write type-safe configs using the same version of postcss-load-config that Vite uses, and users would not need to install their own version of postcss-load-config just to get access to the config typings.