next.js icon indicating copy to clipboard operation
next.js copied to clipboard

`next/lib/find-config` does not support ESM config files

Open ctjlewis opened this issue 3 years ago • 20 comments

Verify canary release

  • [X] I verified that the issue exists in Next.js canary release

Provide environment information

Operating System:
      Platform: linux
      Arch: x64
      Version: #110-Ubuntu SMP PREEMPT Thu Jan 13 19:01:34 UTC 2022
    Binaries:
      Node: 16.10.0
      npm: 7.24.0
      Yarn: 1.22.17
      pnpm: N/A
    Relevant packages:
      next: 12.0.11-canary.19
      react: 17.0.2
      react-dom: 17.0.2

What browser are you using? (if relevant)

No response

How are you deploying your application? (if relevant)

No response

Describe the Bug

Converting Next project to "type": "module", uses Tailwind and PostCSS. next/lib/find-config does not attempt to load via dynamic import and so throws even after converting PostCSS config to ESM:

./node_modules/next/dist/build/webpack/loaders/css-loader/src/index.js??ruleSet[1].rules[2].oneOf[8].use[1]!./node_modules/next/dist/build/webpack/loaders/postcss-loader/src/index.js??ruleSet[1].rules[2].oneOf[8].use[2]!./src/styles/index.css
Error [ERR_REQUIRE_ESM]: require() of ES Module /path/to/my/repo/components/postcss.config.js from /path/to/my/repo/components/node_modules/next/dist/lib/find-config.js not supported.
Instead change the require of postcss.config.js in /path/to/my/repo/components/node_modules/next/dist/lib/find-config.js to a dynamic import() which is available in all CommonJS modules.

Expected Behavior

Should attempt to load configs via ESM-CJS-interoperable default import.

To Reproduce

Convert a Tailwind Next.js project to "type": "module" and run next dev.

ctjlewis avatar Feb 16 '22 21:02 ctjlewis

Next no longer throws with the changes in #34451, but Tailwind will need to make changes in order for Tailwind to not throw:

../../next.js/packages/next/dist/build/webpack/loaders/css-loader/src/index.js??ruleSet[1].rules[2].oneOf[8].use[1]!../../next.js/packages/next/dist/build/webpack/loaders/postcss-loader/src/index.js??ruleSet[1].rules[2].oneOf[8].use[2]!./src/styles/index.css
Error [ERR_REQUIRE_ESM]: require() of ES Module /path/to/my/repo/components/tailwind.config.js from /path/to/my/repo/components/node_modules/tailwindcss/lib/lib/setupTrackingContext.js not supported.
Instead change the require of tailwind.config.js in /path/to/my/repo/components/node_modules/tailwindcss/lib/lib/setupTrackingContext.js to a dynamic import() which is available in all CommonJS modules.

ctjlewis avatar Feb 16 '22 22:02 ctjlewis

Worked around for Tailwind and PostCSS by forcing CJS in the type: module project with .cjs file extension for postcss.config.cjs and tailwind.config.cjs.

ctjlewis avatar Feb 16 '22 22:02 ctjlewis

If anyone is struggling with TailwindCSS + "type: module":

  • Rename the tailwind config file to "tailwind.config.cjs"
  • Put your config from postcss.config.js as JSON to your package.json: under the key "postcss".
  • Remove your postcss.config.js file.
  • Remove the .next folder from your project directory to clear the cache and restart

BB-19 avatar Apr 15 '22 13:04 BB-19

Worked around for Tailwind and PostCSS by forcing CJS in the type: module project with .cjs file extension for postcss.config.cjs and tailwind.config.cjs.

@ctjlewis I'm not sure this works? At least from what I can tell from the way findConfig searches for files. For me, the .cjs versions get ignored. See also here.

@BB-19 I'm not sure this can work for filtering plugins against process.env.NODE_ENV such as written about here

mdaverde avatar Apr 22 '22 17:04 mdaverde

@BB-19 Thank you 🙏 that's the only way I could make my website work. Why is renaming to postcss.config.cjs not sufficient though?

vvo avatar Jun 20 '22 08:06 vvo

@BB-19 is not working for me, what version of next are you using?

error - ./node_modules/next/dist/build/webpack/loaders/css-loader/src/index.js??ruleSet[1].rules[2].oneOf[8].use[1]!./node_modules/next/dist/build/webpack/loaders/postcss-loader/src/index.js??ruleSet[1].rules[2].oneOf[8].use[2]!./src/styles/index.css
/Users/damians/Desktop/predator/tailwind.config.cjs:29
export {};
^^^^^^

SyntaxError: Unexpected token 'export'
    at compileFunction (<anonymous>)
Ready on http://localhost:80

damianobarbati avatar Sep 08 '22 10:09 damianobarbati

@damianobarbati You can’t use exports keyword in a CJS file. Do module.exports = {…}.

ctjlewis avatar Sep 09 '22 06:09 ctjlewis

This is a dealbreaker for me, I need my postcss config to be a module because I share an ESM js dependency between config and code (custom media queries), would be great to hear if it's at least on the roadmap to be fixed

madeleineostoja avatar Oct 27 '22 03:10 madeleineostoja

@damianobarbati

@BB-19 is not working for me, what version of next are you using?

error - ./node_modules/next/dist/build/webpack/loaders/css-loader/src/index.js??ruleSet[1].rules[2].oneOf[8].use[1]!./node_modules/next/dist/build/webpack/loaders/postcss-loader/src/index.js??ruleSet[1].rules[2].oneOf[8].use[2]!./src/styles/index.css
/Users/damians/Desktop/predator/tailwind.config.cjs:29
export {};
^^^^^^

SyntaxError: Unexpected token 'export'
    at compileFunction (<anonymous>)
Ready on http://localhost:80

I was receiving the same error myself when using ts-node with a custom Next.js server. To resolve this, I added tailwind.config.cjs to the ignore option of ts-node. You can do this through the --ignore option or ignore field in ts-node config in the tsconfig.json file. For example, I now have:

...,
"ts-node": {
  "esm": true,
  "ignore": ["node_modules", "tailwind.config.cjs"]
}

The reason why "export {}" is added is explained here. Namely that,

the compiler must emit the export statement in order to ensure that the compiled file is also a Module.

This might only be the case if you set "module": "esnext" in your tsconfig file, which compiles TypeScript files to ESM modules. You might also have "type": "module" in your package.json if that's the case, as I do.

My guess for why adding this to ts-node's ignore field is required is that normally with just tsc TypeScript wouldn't compile tailwind.config.cjs, and I'm guessing that postcss/tailwind dynamically requires it (perhaps something like require('tailwind.config.' + extension) or something like that, which TypeScript can't compile since it can't know what the file is at compile-time), so it would just require it normally and work fine. But with ts-node, since it is now compiling at runtime, the dynamic require would now cause tailwind.config.cjs to be compiled and thus have the export {} line added. Adding the file to the ignore field stops it from doing so.

ConnorLanglois avatar Dec 12 '22 00:12 ConnorLanglois

@BB-19 you saved me, but why does this work?

DannyPark1 avatar Jun 08 '23 06:06 DannyPark1

@BB-19 you saved me, but why does this work?

PostCSS and Tailwind do not support ESM config files. You must rename them to .cjs.

There's no need to move postcss config to package.json and I don't recommend that.

ctjlewis avatar Jun 08 '23 07:06 ctjlewis

如果有人在使用 TailwindCSS +“type: module”时遇到困难:

  • 将 tailwind 配置文件重命名为“tailwind.config.cjs”
  • 将 postcss.config.js 中的配置以 JSON 形式放入 package.json: 的“postcss”键下。
  • 删除 postcss.config.js 文件。
  • 从项目目录中删除 .next 文件夹以清除缓存并重新启动

It's magical !!!

Triment avatar Jul 07 '23 07:07 Triment

If anyone is struggling with TailwindCSS + "type: module": 1.Rename the tailwind config file to "tailwind.config.cjs" 2.Put your config from postcss.config.js as JSON to your package.json: under the key "postcss". 3.Remove your postcss.config.js file. 4.Remove the .next folder from your project directory to clear the cache and restart

@BB-19, No need to rename tailwind.config.js to tailwind.config.cjs. The problem is postcss.config.js, remove it and add the config to package.json. For example

{
...
  "type": "module",
  "postcss": {
    "plugins": {
      "tailwindcss": {},
      "autoprefixer": {}
    }
  },
...
}

For me, Yarn Berry with PnP Strict, the solution for convert next project from CommonJS to ESModule:

  1. Add or update package.json with "type": "module"
  2. Remove postcss.config.js and apply it to package.json with "postcss" json format, see above example
  3. Update next.config.js and tailwind.config.js to ESM format
  4. Add "pnpEnableEsmLoader: true" to .yarnrc.yml
  5. Clear Cache yarn cache clean && rm -rf yarn.lock && yarn install && yarn build

Hope it help to following guys 🤗

Mon-ius avatar Jul 24 '23 19:07 Mon-ius

@Mon-lus Thanks a lot. It worked for me. It would be helpful if you could explain why the error happened. Once again thanks a lot

vishnupb123 avatar Aug 13 '23 14:08 vishnupb123

PostCSS and Tailwind do not support ESM config files

@ctjlewis This is not true anymore, both support ESM:

  • https://github.com/postcss/postcss-load-config/issues/230
  • https://github.com/postcss/postcss-cli/issues/387
  • https://tailwindcss.com/docs/configuration#using-esm-or-type-script

Tailwind CSS config files can also be written in ESM syntax with TypeScript - and this already works now with Next.js.

As far as I can tell, this is a problem with Next.js or some other dependency in between.

karlhorky avatar Nov 13 '23 13:11 karlhorky

In the meantime, before Next.js supports ESM in PostCSS config files, I've opened the following PR to rename postcss.config.js to postcss.config.cjs in create-next-app, so that there is one fewer problem requiring manual intervention when someone wants to add "type": "module" to their package.json:

  • https://github.com/vercel/next.js/pull/58380

karlhorky avatar Nov 13 '23 13:11 karlhorky

Just upgraded to [email protected] and [email protected] and confirmed that the bug still remains, ESM and TypeScript PostCSS formats are still not supported:

karlhorky avatar Dec 08 '23 16:12 karlhorky

Hey guys, try this to see if it works:

  1. Remove file postcss.config.js, and add a new file postcss.config.json with the same config in JSON format:
{
  "plugins": {
    "tailwindcss": {},
    "autoprefixer": {}
  }
}
  1. rm -rf .next && npm run dev

backslash112 avatar Dec 18 '23 01:12 backslash112

@backslash112 I just tried postcss.config.json with tailwind.config.mjs and it worked! 🥳 Thank you.

will-stone avatar Dec 31 '23 12:12 will-stone

@backslash112 I just tried postcss.config.json with tailwind.config.mjs and it worked! 🥳 Thank you.

We want to use postcss.config.mjs, is it possible?

It is not working now.

SalahAdDin avatar Jan 28 '24 01:01 SalahAdDin

Just opened a PR to fix this issue: #63109

phanect avatar Mar 10 '24 15:03 phanect

Thanks for the PR for ESM support @phanect and for the review and merge @huozhi 🙌

I can confirm that [email protected] does have support for the following ESM configurations 🎉

  1. CommonJS project + postcss.config.mjs in ESM format
  2. ESM project + postcss.config.js in ESM format

I left the ReferenceError: module is not defined in ES module scope error in the log output below to show that a postcss.config.mjs file with CommonJS format fails (as expected) 👍

1. CommonJS project + postcss.config.mjs in ESM format

➜  p mkdir postcss-esm-and-ts-configs
➜  p cd postcss-esm-and-ts-configs
➜  postcss-esm-and-ts-configs pnpm create next-app@canary . --app --no-eslint --no-src-dir --import-alias @/\* --tailwind --typescript

.../Library/pnpm/store/v3/tmp/dlx-15463  |   +1 +
.../Library/pnpm/store/v3/tmp/dlx-15463  | Progress: resolved 1, reused 0, downloaded 1, added 1, done
Creating a new Next.js app in /Users/k/p/postcss-esm-and-ts-configs.

Using pnpm.

Initializing project with template: app-tw


Installing dependencies:
- react
- react-dom
- next

Installing devDependencies:
- typescript
- @types/node
- @types/react
- @types/react-dom
- postcss
- tailwindcss

Downloading registry.npmjs.org/next/14.2.0-canary.26: 20.50 MB/20.50 MB, done
Packages: +132
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Downloading registry.npmjs.org/@next/swc-darwin-arm64/14.2.0-canary.26: 36.71 MB/36.71 MB, done
Progress: resolved 140, reused 127, downloaded 5, added 132, done

dependencies:
+ next 14.2.0-canary.26
+ react 18.2.0
+ react-dom 18.2.0

devDependencies:
+ @types/node 20.11.28
+ @types/react 18.2.66
+ @types/react-dom 18.2.22
+ postcss 8.4.35
+ tailwindcss 3.4.1
+ typescript 5.4.2

Done in 4.8s
Initialized a git repository.

Success! Created postcss-esm-and-ts-configs at /Users/k/p/postcss-esm-and-ts-configs

➜  postcss-esm-and-ts-configs git:(main) ls -al
total 136
drwxr-xr-x  15 k  staff    480 Mar 17 16:30 .
drwxr-xr-x  63 k  staff   2016 Mar 17 16:30 ..
drwxr-xr-x  12 k  staff    384 Mar 17 16:30 .git
-rw-r--r--   1 k  staff    391 Mar 17 16:30 .gitignore
-rw-r--r--   1 k  staff   1383 Mar 17 16:30 README.md
drwxr-xr-x   6 k  staff    192 Mar 17 16:30 app
-rw-r--r--   1 k  staff    201 Mar 17 16:30 next-env.d.ts
-rw-r--r--   1 k  staff     92 Mar 17 16:30 next.config.mjs
drwxr-xr-x  12 k  staff    384 Mar 17 16:30 node_modules
-rw-r--r--   1 k  staff    490 Mar 17 16:30 package.json
-rw-r--r--   1 k  staff  34550 Mar 17 16:30 pnpm-lock.yaml
-rw-r--r--   1 k  staff     61 Mar 17 16:30 postcss.config.cjs
drwxr-xr-x   4 k  staff    128 Mar 17 16:30 public
-rw-r--r--   1 k  staff    498 Mar 17 16:30 tailwind.config.ts
-rw-r--r--   1 k  staff    574 Mar 17 16:30 tsconfig.json
➜  postcss-esm-and-ts-configs git:(main) cat postcss.config.cjs
module.exports = {
  plugins: {
    tailwindcss: {},
  },
};
➜  postcss-esm-and-ts-configs git:(main) pnpm dev

> [email protected] dev /Users/k/p/postcss-esm-and-ts-configs
> next dev

  1 export default {
   ▲ Next.js 14.2.0-canary.26
   - Local:        http://localhost:3000

 ✓ Ready in 2.4s
 ○ Compiling / ...
 ✓ Compiled / in 1889ms (523 modules)
 ✓ Compiled in 122ms (244 modules)
^C
➜  postcss-esm-and-ts-configs git:(main) mv postcss.config.cjs postcss.config.mjs
➜  postcss-esm-and-ts-configs git:(main) ✗ pnpm dev

> [email protected] dev /Users/k/p/postcss-esm-and-ts-configs
> next dev

   ▲ Next.js 14.2.0-canary.26
   - Local:        http://localhost:3000

 ✓ Ready in 2.1s
 ○ Compiling / ...
 ⨯ app/layout.tsx
An error occurred in `next/font`.

ReferenceError: module is not defined in ES module scope
    at file:///Users/k/p/postcss-esm-and-ts-configs/postcss.config.mjs:1:1
    at ModuleJob.run (node:internal/modules/esm/module_job:218:25)
    at async ModuleLoader.import (node:internal/modules/esm/loader:329:24)
    at async importModuleDynamicallyWrapper (node:internal/vm/module:431:15)
    at async findConfig (/Users/k/p/postcss-esm-and-ts-configs/node_modules/.pnpm/[email protected][email protected][email protected]/node_modules/next/dist/lib/find-config.js:74:21)
    at async getPostCssPlugins (/Users/k/p/postcss-esm-and-ts-configs/node_modules/.pnpm/[email protected][email protected][email protected]/node_modules/next/dist/build/webpack/config/blocks/css/plugins.js:89:18)
    at async /Users/k/p/postcss-esm-and-ts-configs/node_modules/.pnpm/[email protected][email protected][email protected]/node_modules/next/dist/build/webpack/config/blocks/css/index.js:124:36
    at async /Users/k/p/postcss-esm-and-ts-configs/node_modules/.pnpm/[email protected][email protected][email protected]/node_modules/next/dist/build/webpack/loaders/next-font-loader/index.js:86:33
    at async Span.traceAsyncFn (/Users/k/p/postcss-esm-and-ts-configs/node_modules/.pnpm/[email protected][email protected][email protected]/node_modules/next/dist/trace/trace.js:151:20)
 ⨯ app/layout.tsx
An error occurred in `next/font`.

ReferenceError: module is not defined in ES module scope
    at file:///Users/k/p/postcss-esm-and-ts-configs/postcss.config.mjs:1:1
    at ModuleJob.run (node:internal/modules/esm/module_job:218:25)
    at async ModuleLoader.import (node:internal/modules/esm/loader:329:24)
    at async importModuleDynamicallyWrapper (node:internal/vm/module:431:15)
    at async findConfig (/Users/k/p/postcss-esm-and-ts-configs/node_modules/.pnpm/[email protected][email protected][email protected]/node_modules/next/dist/lib/find-config.js:74:21)
    at async getPostCssPlugins (/Users/k/p/postcss-esm-and-ts-configs/node_modules/.pnpm/[email protected][email protected][email protected]/node_modules/next/dist/build/webpack/config/blocks/css/plugins.js:89:18)
    at async /Users/k/p/postcss-esm-and-ts-configs/node_modules/.pnpm/[email protected][email protected][email protected]/node_modules/next/dist/build/webpack/config/blocks/css/index.js:124:36
    at async /Users/k/p/postcss-esm-and-ts-configs/node_modules/.pnpm/[email protected][email protected][email protected]/node_modules/next/dist/build/webpack/loaders/next-font-loader/index.js:86:33
    at async Span.traceAsyncFn (/Users/k/p/postcss-esm-and-ts-configs/node_modules/.pnpm/[email protected][email protected][email protected]/node_modules/next/dist/trace/trace.js:151:20)
^C
➜  postcss-esm-and-ts-configs git:(main) ✗ vim postcss.config.mjs
➜  postcss-esm-and-ts-configs git:(main) ✗ cat postcss.config.mjs
export default {
  plugins: {
    tailwindcss: {},
  },
};
➜  postcss-esm-and-ts-configs git:(main) ✗ pnpm dev

> [email protected] dev /Users/k/p/postcss-esm-and-ts-configs
> next dev

   ▲ Next.js 14.2.0-canary.26
   - Local:        http://localhost:3000

 ✓ Ready in 1589ms
 ○ Compiling / ...
 ✓ Compiled / in 1931ms (523 modules)
 ✓ Compiled in 168ms (244 modules)
 ○ Compiling /favicon.ico ...
 ✓ Compiled /favicon.ico in 1658ms (530 modules)
^C

2. ESM project + postcss.config.js in ESM format

➜  postcss-esm-and-ts-configs git:(main) ✗ vim package.json
➜  postcss-esm-and-ts-configs git:(main) ✗ cat package.json
{
  "name": "postcss-esm-and-ts-configs",
  "version": "0.1.0",
  "private": true,
  "type": "module",
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start",
    "lint": "next lint"
  },
  "dependencies": {
    "react": "^18",
    "react-dom": "^18",
    "next": "14.2.0-canary.26"
  },
  "devDependencies": {
    "typescript": "^5",
    "@types/node": "^20",
    "@types/react": "^18",
    "@types/react-dom": "^18",
    "postcss": "^8",
    "tailwindcss": "^3.4.1"
  }
}
➜  postcss-esm-and-ts-configs git:(main) ✗ mv postcss.config.mjs postcss.config.js
➜  postcss-esm-and-ts-configs git:(main) ✗ pnpm dev

> [email protected] dev /Users/k/p/postcss-esm-and-ts-configs
> next dev

   ▲ Next.js 14.2.0-canary.26
   - Local:        http://localhost:3000

 ✓ Ready in 1679ms
 ○ Compiling / ...
 ✓ Compiled / in 1875ms (523 modules)
 ✓ Compiled in 117ms (244 modules)
 ○ Compiling /favicon.ico ...
 ✓ Compiled /favicon.ico in 1663ms (530 modules)

karlhorky avatar Mar 17 '24 15:03 karlhorky

One thing that is NOT yet supported is the postcss.config.ts file format supported by postcss-load-config:

➜  postcss-esm-and-ts-configs git:(main) ✗ mv postcss.config.mjs postcss.config.ts
➜  postcss-esm-and-ts-configs git:(main) ✗ pnpm dev

> [email protected] dev /Users/k/p/postcss-esm-and-ts-configs
> next dev

   ▲ Next.js 14.2.0-canary.26
   - Local:        http://localhost:3000

 ✓ Ready in 1666ms
 ○ Compiling / ...
 ✓ Compiled / in 1648ms (523 modules)
 ○ Compiling /favicon.ico ...
 ✓ Compiled /favicon.ico in 793ms (530 modules)
^C

It looks like the compilation works, but this results in an unstyled application.

But since this was not the main request by @ctjlewis in this issue, and appeared later in the issue comments, it's probably best to open a new issue for this.

karlhorky avatar Mar 17 '24 15:03 karlhorky

One thing that probably could be still improved here is altering create-next-app to create postcss.config.mjs file with ESM format instead of the postcss.config.cjs file that is currently created.

I opened a PR for this here:

  • https://github.com/vercel/next.js/pull/63380

karlhorky avatar Mar 17 '24 16:03 karlhorky

@karlhorky Thanks for testing. Yes, *.config.ts is out of scope of the PR I created this time and not supported yet, unfortunately.

phanect avatar Mar 17 '24 20:03 phanect

@karlhorky Thanks for testing. Yes, *.config.ts is out of scope of the PR I created this time and not supported yet, unfortunately.

So, right now we can use postcss.config.mjs, right?

SalahAdDin avatar Mar 18 '24 13:03 SalahAdDin

@SalahAdDin Yes, the latest canary release should support *.config.mjs now. I guess the stable version does not support it yet until the next release.

phanect avatar Mar 18 '24 14:03 phanect

This closed issue has been automatically locked because it had no new activity for 2 weeks. If you are running into a similar issue, please create a new issue with the steps to reproduce. Thank you.

github-actions[bot] avatar Apr 02 '24 00:04 github-actions[bot]