Add ESM support to typescript config files
NashJames opened this issue · 12 comments
Hi! It would be quite nice to start writing postcss config files with full ESM + TS support since it seems to be becoming standard with most popular tools. As an example, a postcss.config.ts
file written as such:
import type { Config } from 'postcss-load-config'
export default {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
} satisfies Config
If it is any help, I noticed Tailwind made some small mention of the libraries they used to handle this in a blog post.
Thanks.
I think we already support ESM configs since 4.0.
What we need to add for TS support?
For a minimal example:
pnpm create-next-app
and click Enter through all the options- Remove the
postcss.config.js
file - Add a
postcss.config.ts
file and add the above config - Launch the app with
pnpm dev
Fairly sure the problematic bit is the export default
as it acts slightly differently to module.exports
@NashJames can you do a investigation and find what we should change?
Sure. I had a quick look at tailwind and found these two files:
https://github.com/tailwindlabs/tailwindcss/blob/master/loadConfig.js
https://github.com/tailwindlabs/tailwindcss/blob/master/src/lib/load-config.ts
An example of it being used here: https://github.com/tailwindlabs/tailwindcss/blob/e853901591c410ec0ce053c6fc57c92e4ff11548/src/cli/build/plugin.js#L151
I think the config just needs sending through this transformer
I did skim the whole project earlier, and just now that PR. I'm not exactly sure what you're asking but I'm not sure it includes anything to handle an export default? You seem to use lilconfig
and even they suggest using loaders for ESM which I couldn't find any instances of in the repo?
@michael42 can you explain how we did ESM support in your PR and what to do to use it with .ts
extension?
@NashJames what is your tsconfig.json
? Do you have type: module
in package.json
?
I have no trouble doing this for any other configuration files (I'm assuming they all added support) so I don't think it'll be my setup being problematic. Unless you have trouble re-creating it?
what is your
tsconfig.json
?
{
"compilerOptions": {
"target": "es2022",
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve",
"incremental": true,
"plugins": [{ "name": "next" }],
"paths": {
"@public/*": ["./public/*"],
"@components/*": ["./src/components/*"],
"@pages/*": ["./src/pages/*"],
"@data/*": ["./src/data/*"],
"@lib/*": ["./src/lib/*"]
},
"noImplicitAny": true,
"noImplicitThis": true,
"strictNullChecks": true
},
"include": ["next-env.d.ts", ".next/types/**/*.ts", "**/*.ts", "**/*.tsx"],
"exclude": ["node_modules"]
}
Do you have
type: module
inpackage.json
?
Nope
@NashJames: Default exports should be supported, in fact (for most file types, it's the only kind of export that's supported, as even CommonJS files are loaded with import(...)
.
@ai: I didn't, however, get a .ts
-file that compiles to ESM to work with an unmodified postcss-load-config
. I think that's because postcss-load-config
enables ts-node
by calling require('ts-node').register()
, as that API doesn't support ESM as far as I know.
Supporting ESM in .ts
-files should be possible in postcss-load-config
, but personally, I don't see that as worthwhile. Using a simple .js
/.mjs
file, like /** @type {import("postcss-load-config").Config} */ export default {}
):
- can be immediately executed, because it doesn't need a transpiler (ts-node? plain tsc? esbuild? swc? babel? tsx?)
- doesn't depend on
tsconfig.json
settings (during run-time) - is just as type-safe as
.ts
-file, because TypeScript can also check.js
files (enabled by default)- code completion by the TS language service is the same
- TypeScript errors when compiling with
tsc
are the same
@NashJames if you don’t have type: module
in package.json
then all .ts
files will be treated as CJS files.
I'm agreed with everything said and am aware that there's no real benefit to TS config files. I'm quite happy to use JS or type:module
in projects, but I figure it was worth raising for consistency.
I'm experiencing a lot more libraries encouraging TS as their default config file format with ESM defaults and satisfy typing examples. I think there's a huge preference to use TS for everything now and it's a small surprise when you find something not supported out-of-the-box. Particularly, ESM and TS both supported but not at the same time was a little weird.
Even though there's no material benefit to adding the support natively, it may save people time figuring the same out in the future. I reckon it is worth keeping open until either the API has an update or someone is looking to contribute. Especially since there's no harm to adding support (the transpilation cost should be next to nothing?).
I'll make the issue title a little clearer since this only affects .ts
files.
Thanks for the release postcss-load-config@5.0.0
with full ESM support in postcss.config.ts
with "type": "module"
@brc-dd and @ai 🙌