postcss / postcss-load-config

Autoload Config for PostCSS
MIT License
638 stars 71 forks source link

Add ESM support to typescript config files #246

Closed NashJames closed 8 months ago

NashJames commented 1 year ago

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.

ai commented 1 year ago

I think we already support ESM configs since 4.0.

What we need to add for TS support?

NashJames commented 1 year ago

For a minimal example:

  1. pnpm create-next-app and click Enter through all the options
  2. Remove the postcss.config.js file
  3. Add a postcss.config.ts file and add the above config
  4. Launch the app with pnpm dev

Fairly sure the problematic bit is the export default as it acts slightly differently to module.exports

ai commented 1 year ago

@NashJames can you do a investigation and find what we should change?

NashJames commented 1 year ago

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

ai commented 1 year ago

Can you check that PR (which we already merged)?

https://github.com/postcss/postcss-load-config/pull/234

NashJames commented 1 year ago

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?

ai commented 1 year ago

@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?

NashJames commented 1 year ago

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 in package.json?

Nope

michael42 commented 1 year ago

@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 {}):

ai commented 1 year ago

@NashJames if you don’t have type: module in package.json then all .ts files will be treated as CJS files.

NashJames commented 1 year ago

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.

karlhorky commented 5 months ago

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 🙌