Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Incompatibility with Node.js v22.12.0: ReferenceError: require is not defined (But Works with v22.11.0) #56155

Closed
Vanakeethan opened this issue Dec 6, 2024 · 12 comments
Labels
loaders Issues and PRs related to ES module loaders module Issues and PRs related to the module subsystem.

Comments

@Vanakeethan
Copy link

Vanakeethan commented Dec 6, 2024

Version

node v22.12.0(LTS)

Platform

Windows 11 23H2, 64-bit
Node.js v22.12.0

What steps will reproduce the bug?

  1. Install Node.js v22.12.0.
  2. Clone the repository.
  3. Run npm install.
  4. Run npm run dev.

How often does it reproduce? Is there a required condition?

The issue consistently reproduces every time the application is run using Node.js v22.12.0.

What is the expected behavior? Why is that the expected behavior?

The application should start without any errors.

What do you see instead?

The application fails with the error:
ReferenceError: require is not defined

const path = require("path");
^
ReferenceError: require is not defined
at file:///path/to/tailwind.config.js:1:14

Additional information

**### ## Compatibility

Node.js Compatibility

  • This project is currently incompatible with Node.js v22.12.0 due to stricter module handling.
    - Use Node.js v22.11.0 for a stable experience.

Workaround

To run the project successfully:

  1. Install Node.js v22.11.0:
    nvm install 22.11.0
    nvm use 22.11.0 
    

Download the Node.js v22.11.0 for a stable experience.

https://drive.google.com/file/d/1fjLXb1xUMowMj3F9FmDt1dw0XJOuYflP/view?usp=sharing

@Vanakeethan Vanakeethan changed the title Incompatibility with Node.js v22.12.0: ReferenceError: require is not defined Incompatibility with Node.js v22.12.0: ReferenceError: require is not defined (But Works with v22.11.0) Dec 6, 2024
@joyeecheung
Copy link
Member

joyeecheung commented Dec 6, 2024

Clone the repository.

There doesn't seem to be a repository link in the OP?

This seems similar to #56140 - you may have "type": "module" in your package.json while having a .js file using require, which is technically a bug by the interpretation of Node.js's builtin module loaders, but was probably masked by some toolchain that incorrectly monkey patches Node.js's internals (e.g. missing the third argument of the internal they patched). If you do, solution would be similar to what's mentioned in #56140 (comment) (either rename your config file to use tailwind.config.cjs, or use ESM syntax in your .js file)

@virtuallyunknown
Copy link

virtuallyunknown commented Dec 6, 2024

Hey @joyeecheung I am having a similar issue. My code works with v22.11.0, but not with v22.12.0 or v23.3.0.

Here is a minimal reproducible repo:

https://github.com/virtuallyunknown/node-error

# ✅ works
nvm use 22.11.0
node build.js
# ❌ fails
nvm use 22.12.0
node build.js
# ❌ fails
nvm use 23.3.0
node build.js

Renaming to .cjs allows build.js to pass with the following warnings:

(node:5485) Warning: To load an ES module, set "type": "module" in the package.json or use the .mjs extension.
(Use `node --trace-warnings ...` to show where the warning was created)
(node:5485) Warning: To load an ES module, set "type": "module" in the package.json or use the .mjs extension.

But is renaming to .cjs the only solution here? I have dozens of projects using build scripts like these, so it's going to be an absolute nightmare renaming each one of them.

#56140 explains that you can use ESM syntax in your tailwind.config.js file, but my file is already using ESM syntax:

import { fontFamily } from 'tailwindcss/defaultTheme.js';

/** @type {import('tailwindcss').Config} */
export default {
    content: ['./src/**/*.tsx'],
    theme: {
        extend: {
            fontFamily: {
                'inter': ['Inter', ...fontFamily.sans],
                'source-code-pro': ['"Source Code Pro"', ...fontFamily.mono],
            }
        },
    },
}

@joyeecheung
Copy link
Member

joyeecheung commented Dec 6, 2024

I am not sure what tailwind does but judging from

but my file is already using ESM syntax

it seems to be monkey patching Node.js CJS loader internals to magically transpile ESM to CJS and maybe writing them to .js files with "type": "module" in the package.json and introduce glitches. It may be something that can be fixed on tailwind's side, if they are already monkey patching the CJS loader, they could probably be updated to patch the newer CJS loaders internals, er, less incorrectly.

@virtuallyunknown
Copy link

I am not sure what tailwind does but judging from

but my file is already using ESM syntax

it seems to be monkey patching Node.js CJS loader internals to magically transpile ESM to CJS and maybe writing them to .js files with "type": "module" in the package.json and introduce glitches. It may be something that can be fixed on tailwind's side, if they are already monkey patching the CJS loader, they could probably be updated to patch the newer CJS loaders internals, er, less incorrectly.

I think the issue was that I was not using extensionless import. I apologize if my terminology is incorrect.

import { fontFamily } from 'tailwindcss/defaultTheme.js';
// vs
import { fontFamily } from 'tailwindcss/defaultTheme';

When I use extensionless import, I only get a warning, but the build.js script works.

(node:40614) ExperimentalWarning: CommonJS module /path/to/node-error/node_modules/tailwindcss/lib/lib/load-config.js is loading ES Module /path/to/node-error/tailwind.config.js using require().
Support for loading ES Module in require() is an experimental feature and might change at any time
(Use `node --trace-warnings ...` to show where the warning was created)

The examples in the tailwind docs also use extensionless imports (although their example is CJS, not sure if that makes any difference), so I think it's probably my own fault here.

@joyeecheung
Copy link
Member

joyeecheung commented Dec 6, 2024

I believe extensionless import is also how it's generally called here, yes ;)

When I use extensionless import, I only get a warning, but the build.js script works.

I think that warning should only be on v23 if it's from node_modules, and should not show up on v22 (v23 will have that patch later). Is this on v23? If it's from v22 that might be a bug.

Anyway, my speculation is that when you use extensionless import, you are writing faux ESM instead of native ESM (Node.js's native ESM does not support extensionless import unless the package specify the target in their export conditions, but I don't see any in tailwindcss's package.json), and maybe tailwindcss's patching generally expects that you write faux ESM when you do write ESM. If somehow your file is loaded just fine by Node.js without erroring, it is somehow not good for them because their patching code won't get a chance to run?

@virtuallyunknown
Copy link

Hey @joyeecheung the warning was on v23.3, but give me ~20 minutes and I will come back with results from 22.12.

Anyway, my speculation is that when you use extensionless import, you are writing faux ESM instead of native ESM (Node.js's native ESM does not support extensionless import unless the package specify the target in their export conditions, but I don't see any in tailwindcss's package.json), and maybe tailwindcss's patching generally expects that you write faux ESM when you do write ESM. If somehow your file is loaded just fine by Node.js without erroring, it is somehow not good for them because their patching code won't get a chance to run?

I am honestly not sure, my understanding on the topic of imports/exports is probably above-average yet still limited, and I haven't written any CJS related code in years (migrated to full ESM long ago). So I have no clue what the folks over at tailwind might be doing.

(Node.js's native ESM does not support extensionless import unless the package specify the target in their export conditions, but I don't see any in tailwindcss's package.json

Yep, I remember reading about this a while ago, so I am not exactly sure how I ended with .js import. It is worth mentioning that 22.11 supports both extension and extensionless, but that is not to say I was writing correct code.

@virtuallyunknown
Copy link

I think that warning should only be on v23 if it's from node_modules, and should not show up on v22 (v23 will have that patch later). Is this on v23? If it's from v22 that might be a bug.

Hey again, I can confirm that extensionless

import { fontFamily } from 'tailwindcss/defaultTheme';

on 22.12 does NOT produce any warnings or errors, and neither does 22.11.

And some extra info, 22.11 allows both with no errors or warnings (which is how I was using it before upgrading nodejs today):

import { fontFamily } from 'tailwindcss/defaultTheme';
import { fontFamily } from 'tailwindcss/defaultTheme.js';

Cheers!

@joyeecheung joyeecheung added module Issues and PRs related to the module subsystem. loaders Issues and PRs related to ES module loaders labels Dec 6, 2024
theoludwig added a commit to theoludwig/theoludwig that referenced this issue Dec 6, 2024
@targos
Copy link
Member

targos commented Dec 7, 2024

Tailwind uses a module called jiti to load the configuration file: https://github.com/tailwindlabs/tailwindcss/blob/f875ab9706cae8262e15e5b382580fc8e2d4197f/src/lib/load-config.ts#L34-L55

That module is doing a lot of complicated things with Node.js internals, so it has probably been broken in some way. See https://github.com/unjs/jiti/blob/ad6191f04624badf2112651217bc17008a9bde50/src/eval.ts for example.

mnonnenmacher added a commit to eclipse-apoapsis/ort-server that referenced this issue Dec 10, 2024
Convert the Tailwind CSS config file from CSJ to ESM syntax to fix the
build with Node 22.12.0 [1].

[1]: nodejs/node#56155

Signed-off-by: Martin Nonnenmacher <[email protected]>
mnonnenmacher added a commit to eclipse-apoapsis/ort-server that referenced this issue Dec 10, 2024
Convert the Tailwind CSS config file from CSJ to ESM syntax to fix the
build with Node 22.12.0 [1].

[1]: nodejs/node#56155

Signed-off-by: Martin Nonnenmacher <[email protected]>
mnonnenmacher added a commit to eclipse-apoapsis/ort-server that referenced this issue Dec 10, 2024
Convert the Tailwind CSS config file from CJS to ESM syntax to fix the
build with Node 22.12.0 [1].

[1]: nodejs/node#56155

Signed-off-by: Martin Nonnenmacher <[email protected]>
github-merge-queue bot pushed a commit to eclipse-apoapsis/ort-server that referenced this issue Dec 10, 2024
Convert the Tailwind CSS config file from CJS to ESM syntax to fix the
build with Node 22.12.0 [1].

[1]: nodejs/node#56155

Signed-off-by: Martin Nonnenmacher <[email protected]>
@mteterel
Copy link

mteterel commented Dec 11, 2024

Whoever decided it was a good idea to push this such impactful change into a minor version (in the LTS branch !) clearly didn't think of the pain it is to have to issue a hotfix for builds failing overnight with all the tooling working against you ...

@joyeecheung
Copy link
Member

joyeecheung commented Dec 11, 2024

The backport of the semver-minor was requested by many people, so it's not a decision made by any individual but a large group of users and especially package maintainers who look forward to shipping ESM as-is and not having to maintain dual shipping.

The issues here is likely caused by third-party libraries patching/using the Node.js internals, in that case it's already risky business and even some small subtle refactoring of the internals in a semver-patch release can already make you have to push a hotfix to work around their bug. If a third-party library is relying on a bug or how the internals work which there is no stability guarantee for, the issue should be brought to their issue tracker. Otherwise we'll at least need a reproduction that doesn't use any third-party code and doesn't use any undocumented internals to fix anything.

@joyeecheung
Copy link
Member

joyeecheung commented Dec 17, 2024

This seems to be caused by some unreliable assumptions jiti makes about Node.js internals and probably has been fixed in the latest releases of jiti: unjs/jiti#346 (comment)

@joyeecheung
Copy link
Member

Closing since it seems to be fixed elsewhere.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
loaders Issues and PRs related to ES module loaders module Issues and PRs related to the module subsystem.
Projects
None yet
Development

No branches or pull requests

5 participants