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

v4 can't be imported in node #365

Open
g012 opened this issue Jun 9, 2022 · 114 comments
Open

v4 can't be imported in node #365

g012 opened this issue Jun 9, 2022 · 114 comments

Comments

@g012
Copy link

g012 commented Jun 9, 2022

Hello,

I'm not knowledgeable at all in all the module formats / import mess of javascript / node, but I'm using KeystoneJS and I import nanoid in it. Since version 4 (2 days ago), I have this error :

Error [ERR_REQUIRE_ESM]: require() of ES Module /node_modules/nanoid/async/index.js from schema.ts not supported. Instead change the require of index.js in schema.ts to a dynamic import() which is available in all CommonJS modules.

This is how I've always imported nanoid :

import { nanoid } from 'nanoid/async';

Reverting to 3.3.4 works.
I see in the commit comment that you removed CJS support, but as I understand, using this import statement, I'm using the new thingy module stuff, not CJS which uses require instead, and you have "type: module" in your package.json, so I really don't know what's wrong here.

Any idea what I'm doing wrong ? Thanks !

@PoProstuWitold
Copy link

I'm also having this issue

@marekkobida
Copy link

Me too.

@danielweck
Copy link

This is a feature, not a bug. See the changelog for details of the breaking change in version 4.0 (semantic versioning major increment): https://github.com/ai/nanoid/blob/main/CHANGELOG.md#40

@danielweck
Copy link

Also see the author's feedback in this previously-closed issue: #364 (comment)

@ai
Copy link
Owner

ai commented Jun 9, 2022

Check your TS config.

Seems like TS convert import in source TS sources to require. I use this option in tsconfig.json: "module": "esnext" (buy you may need to convert the whole app to TS).

@g012
Copy link
Author

g012 commented Jun 9, 2022

This is a feature, not a bug. See the changelog for details of the breaking change in version 4.0 (semantic versioning major increment): https://github.com/ai/nanoid/blob/main/CHANGELOG.md#40

This doesn't help at all, we saw the comment in the commit on main page of code repo, as stated.

Also see the author's feedback in this previously-closed issue: #364 (comment)

In this one the guy says he was using require, and is told to move to import. As stated, I (we ?) are already using import since long.

Check your TS config.

Seems like TS convert import in source TS sources to require. I use this option in tsconfig.json: "module": "esnext" (buy you may need to convert the whole app to TS).

Thanks, I've tried changing module: "commonjs" to module: "esnext", but it made no difference. Could you share your whole tsconfig file ? Here's mine:

  "compilerOptions": {
    "target": "esnext",
    "module": "esnext",
    "strict": true,
    "noEmit": true,
    "esModuleInterop": true,
    "forceConsistentCasingInFileNames": true,
    "jsx": "react"
  }
}

@ai
Copy link
Owner

ai commented Jun 9, 2022

Maybe you should remove "esModuleInterop": true,. Try to call tcs file.ts to be sure that you have import in the compiled results.

Here is one of my examples https://github.com/hplush/slowreader/blob/main/tsconfig.json

@danielweck
Copy link

Hello @g012 ,
have you seen this doc?
https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c

Support for ESM depends heavily on tooling, for example you may have different tsconfig.json settings for your unit tests, your dev builds, and your production release ... depending on whether your codebase is managed with WebPack, Rollup, Vite, Jest, Vitest, etc.

The author of NanoID said that he will kindly continue to offer off-the-shelf compatibility with CommonJS by maintaining v3 in parallel to ESM v4, but I am concerned that noise/signal ratio will increase in this issue tracker due to v4 support queries.

As far as I can tell there are no problems with NanoID's published package.json export map etc. so I think it would make sense to continue such general ESM/CJS conversations in a GitHub discussion instead.

:)

@amir-arad
Copy link

amir-arad commented Jun 13, 2022

I'm having the same issue in two flavors. first one was described above. second one is:

 Details:

    /home/circleci/project/node_modules/nanoid/index.js:1
    ({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,jest){import { randomFillSync } from 'crypto'
                                                                                      ^^^^^^

    SyntaxError: Cannot use import statement outside a module

    > 1 | import { customAlphabet } from 'nanoid';
        | ^
      2 |
      3 | const letters = customAlphabet('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ', 1);
      4 | const alphanumeric = customAlphabet('0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ', 5);

in short, I need to turn on an experimental feature in node to enable ESModules import in Jest.
I can't wait for ESModules to become a standard, but right now it's not yet frictionless.

this is my update PR: starwards/starwards#847

@picardplaisimond
Copy link

I think this decision was made far too early. ESM has just started to be supported by NodeJS. I'm not sure if I want to refactor my whole "production application" for ESM right now.

I just wanted to point that out.

@danielweck
Copy link

. I'm not sure if I want to refactor my whole "production application" for ESM right now.

"We will support 3.x branch with CommonJS for users who can’t migrate to ESM"

https://github.com/ai/nanoid/blob/main/CHANGELOG.md#40

@g012
Copy link
Author

g012 commented Jun 17, 2022

Hello @g012 , have you seen this doc? https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c

Support for ESM depends heavily on tooling, for example you may have different tsconfig.json settings for your unit tests, your dev builds, and your production release ... depending on whether your codebase is managed with WebPack, Rollup, Vite, Jest, Vitest, etc.

The author of NanoID said that he will kindly continue to offer off-the-shelf compatibility with CommonJS by maintaining v3 in parallel to ESM v4, but I am concerned that noise/signal ratio will increase in this issue tracker due to v4 support queries.

As far as I can tell there are no problems with NanoID's published package.json export map etc. so I think it would make sense to continue such general ESM/CJS conversations in a GitHub discussion instead.

:)

Hi Daniel,

Yes I think you're right, the Keystone JS toolset converts typescript to CJS, and if I disable that, I get lint warnings for k6 core and some others, so I've decided to stick with branch 3 until everything migrates.

Thanks for the help !

@garretthogan
Copy link

This is a feature, not a bug. See the changelog for details of the breaking change in version 4.0 (semantic versioning major increment): https://github.com/ai/nanoid/blob/main/CHANGELOG.md#40

Really terrible decision. Was gonna use this in place of shortid because apparently this is more secure? But since I literally can't import the latest I'm just gonna keep using shortid. Good luck building a product that people can't use!

@danielweck
Copy link

... since I literally can't import the latest I'm just gonna keep using shortid.

"We will support 3.x branch with CommonJS for users who can’t migrate to ESM"

https://github.com/ai/nanoid/blob/main/CHANGELOG.md#40

@weyert
Copy link

weyert commented Jun 26, 2022

Are you planning any security updates for 3.x? Can you clarify what you mean with 'support 3.x branch'?

@ai
Copy link
Owner

ai commented Jun 26, 2022

Are you planning any security updates for 3.x? Can you clarify what you mean with 'support 3.x branch'?

Of course. All fixes will be backported.

@ayushsharma82
Copy link

Use this version while the author fixes commonjs issue:

npm i -S nanoid@^3.0.0

@weyert
Copy link

weyert commented Jun 28, 2022

Whatever works for the maintainer. I am happy the person still maintains the CommonJS version for security updates :)

@ai
Copy link
Owner

ai commented Jun 28, 2022

Theres no harm in supporting commonJS neither does it has any performance ,build or maintainability problems. Its too early to move into ESM imo

Dual ESM/CJS packages is not a good thing. As a developer of dual-publish I can say it without a doubt.

  1. You need to duplicate every file in npm package which increase node_modules size.
  2. It leads to expected problems in some non-standard systems (for instance, Jest is using custom ESM resolver and dual packages could increase the error rate).
  3. Dual packages requires extra build step (like dual-publish or babel). With ESM-only you can publish your repository directly.
  4. It also make more complex another tools. For instance, Size Limit will require extra plugin.
  5. There is no simple way to use version from repository (for instance, to test PR) without some painful bugs. Because dual packages requires build step.

Current state of ecosystem when we need to support both ESM and CJS is very hard for maintainers. Our community need to migrate to ESM-only future. It was already a few years since ESM announce.

@Julusian
Copy link

Julusian commented Jun 29, 2022

Current state of ecosystem when we need to support both ESM and CJS is very hard for maintainers.

That is true, but esm only packages can be very hard for users ;)

Im perfectly happy to keep using v3 until I can switch things to ESM (there is already a pretty long list of other dependencies that cant be updated), but that switch is currently impossible due to electron not supporting ESM in the backend at all, and jest needing nodejs to finish some features before they can have feature parity with CJS.
I personally would have no problem with libraries pushing users to ESM if nodejs & electron were ready for it. But they aren't, so even though ESM has been around for years, the push from library authors feels premature to me.

@ai
Copy link
Owner

ai commented Jun 29, 2022

I personally would have no problem with libraries pushing users to ESM if nodejs & electron were ready for it

Electron and Node.js will not be ready for years if there will not be push from the community.

It is better to support ESM issues in Electron and Node.js.

Im perfectly happy to keep using v3 until I can switch things to ESM

You do not need to always use the latest version of the dependency. You need to use the latest supported version. Both branches 3.x and 4.x are supported. Don’t worry that you are on 3.x branch.

@weyert
Copy link

weyert commented Jun 29, 2022

I don't really mind maintainers of packages switching to ESM. It's their project. Only I wish they don't forget their old CommonJS packages when vulnerabilities in dependencies or similar occur. So I was glad to hear this is the case for this super useful package :)

I really need to find out how I can get ESM modules working with Jest. Or is there a better alternative for Jest that has better ESM support? Anyone tried Vitest? Looks like its compatible with Jest's expect?

@ai
Copy link
Owner

ai commented Jun 29, 2022

Or is there a better alternative for Jest that has better ESM support?

For simple Node.js libraries uvu is better.

For React projects Vitest is the best option.

@Julusian
Copy link

You do not need to always use the latest version of the dependency. You need to use the latest supported version. Both branches 3.x and 4.x are supported. Don’t worry that you are on 3.x branch.

Exactly. Im using 4.x in some projects and 3.x in others, depending on whether they are ESM or not. Hopefully 3.x will get updates for a few years, as I expect ESM wont be usable for everyone for at least a couple more years

I really need to find out how I can get ESM modules working with Jest. Or is there a better alternative for Jest that has better ESM support? Anyone tried Vitest? Looks like its compatible with Jest's expect?

I believe that Jest does mostly work, but they don't have feature parity with CJS. jestjs/jest#9430
The main blocker for me is the lack of mock support, which I believe is blocked on the required nodejs features still being experimental.

@dannyglovory
Copy link

Use this version while the author fixes commonjs issue:

npm i -S nanoid@^3.0.0

Thank you, it's works for me

Repository owner deleted a comment from jpike88 Jul 11, 2022
@ai
Copy link
Owner

ai commented Jul 11, 2022

Just stay on Nano ID 3 if you have CJS project. We will support Nano ID 3 for a few years.

I delete a very hacky and dangerous advice of crazy wraps to load ESM to CJS.

@jpike88
Copy link

jpike88 commented Jul 11, 2022

No, I'm going to use v4 using the 'hacky and dangerous' method because I don't want to worry about being stuck on an obsolete version which will not be supported soon.

@ai
Copy link
Owner

ai commented Jul 11, 2022

I don't want to worry about being stuck on an obsolete version which will not be supported soon.

Nano ID 3 is not obsolete. It is a parallel version. We will support it for a few years.

Just use Nano ID 3.x. There are no rational problems with this version.

@jpike88
Copy link

jpike88 commented Jul 11, 2022

If a version of an open source node library has got an end of life announced for it, I consider it already on its way out. It's how I and many other devs out there work, and it's all about minimising technical debt.

That will be the only dependency of over 50 in my package.json I have to worry about pinning, which I've managed to avert worrying about by doing this 'super dangerous hack' (which isn't really that dangerous at all, I have an integration test that covers usage of it and continuously audit my packages).

The problem here isn't whether or not people should stay on v3 or not, it's about understanding the reality of many projects out there that do not have the resources or priorities around upgrading to ESM. ESM isn't a magical solution to dependency security, you can still do plenty of mischief whether your lib is used in CJS or ESM mode.

@cstavaru
Copy link

I ran into the same problem today.

I was also using the node-fetch package whose authors made the same mistake as nanoid: their current major version is ESM-only. Almost two years later since this change and their "old" CJS release is still downloaded 25 times more frequently than their current ESM-only release (you can check NPM stats).

I wish package authors would understand that people can't switch to ESM because this would mean breaking the vast majority of their current dependencies. Switching popular packages to ESM-only will end up causing pain to others for 5 years or so and with the shiny new bleeding-edge version being barely used. So a lose-lose situation.

The final solution to this kind of issue will probably be solved in the Javascript standard which must provide a compatible upgrade path without these showstopper compatibility issues.

@sugoidesune
Copy link

This should be front page on the readme because this is wasting a lot of peoples time.

@ai
Copy link
Owner

ai commented Feb 28, 2023

@sugoidesune it is in Install section of docs

https://github.com/ai/nanoid#install

@eezing
Copy link

eezing commented Mar 12, 2023

@ai Thanks for choosing to support CommonJS in v3.

I tried converting a monorepo to ESM; builds and runs fine, but Jest blew up. No dice for now.

@ai
Copy link
Owner

ai commented Mar 12, 2023

@eezing this is why I moved from Jest

@dcsan
Copy link

dcsan commented Mar 14, 2023

@ai what did you move to? is there some other testing framework that works with nanoid ?

@kehiy
Copy link

kehiy commented Mar 17, 2023

thats worked for me :
npm uninstall nanoid
npm install nanoid@3.3.4

@iambumblehead
Copy link

iambumblehead commented Mar 24, 2023

@dcsan not ai, but want to share this opinion after using different test frameworks,

  • for small applications using latest version of node: use node's native test runner, node:test,
  • for everything else: use ava. use node:test for everything -- recent versions of node:test perform as well at least as well as ava

@JoshMcCullough
Copy link

Really terrible decision. Was gonna use this in place of shortid because apparently this is more secure? But since I literally can't import the latest I'm just gonna keep using shortid. Good luck building a product that people can't use!

@garretthogan you should amend your comment, knowing that v3 will continue to support CommonJS, and v4 was clearly indicated to support only ESM.

Thank you @ai for supporting both!

@qiqo
Copy link

qiqo commented Jun 20, 2023

Joining the party late, after much reading to make this work in a pretty large NestJS production project we have just migrated, I've installed version 3.3.5 and it works like a charm. Thanks @ai for your patience on some of the not-so-nice comments I've been seeing.

To all, its an open source project and let's just be thankful that the maintainer does what he can for OSS. If something doesn't fit well in your apps, just fork and apply the changes you see fit. I don't think its fair to resort to bashing.

Cheers 🖖

@vdjurdjevic
Copy link

Just to add my opinion :) I also don't like this. I like to keep my dependencies up to date, and this is the only one that has to be v3 instead of v5 now..

image

This yellow circle really messes with my developer OCD :)

@ai
Copy link
Owner

ai commented Sep 16, 2023

@vdjurdjevic if you like to keep everything fresh, you have an another reason to move to ESM. ESM is the future of imports in JS. Keep your project fresh too. 😊

@vdjurdjevic
Copy link

Trust me I tried :) But everything started to break, spent few hours trying to make it work and then decided to go back. It's medium size project, with 70 dependencies, it's not that easy to switch

@garretthogan
Copy link

@vdjurdjevic if you like to keep everything fresh, you have an another reason to move to ESM. ESM is the future of imports in JS. Keep your project fresh too. 😊

I admire the attempted prescience but please stop making these decisions for developers that take pride in their work. We will decide the future of our own stack whether it includes this dep or not.

@markhughes
Copy link

@vdjurdjevic if you like to keep everything fresh, you have an another reason to move to ESM. ESM is the future of imports in JS. Keep your project fresh too. 😊

I admire the attempted prescience but please stop making these decisions for developers that take pride in their work. We will decide the future of our own stack whether it includes this dep or not.

v3 is still supported

dmecke added a commit to dmecke/game-engine that referenced this issue Nov 9, 2023
iwasrobbed added a commit to iwasrobbed/tldraw that referenced this issue Nov 17, 2023
see ai/nanoid#365 and

Error: require() of ES Module /Users/rob/fastlane-web/node_modules/@tldraw/store/node_modules/nanoid/index.js from /Users/rob/fastlane-web/node_modules/@tldraw/store/dist-cjs/lib/RecordType.js not supported.
Instead change the require of index.js in /Users/rob/fastlane-web/node_modules/@tldraw/store/dist-cjs/lib/RecordType.js to a dynamic import() which is available in all CommonJS modules.
@jgillick
Copy link

You should be able to wrap this with a dynamic import:

For example:

src/lib/nanoid.ts

import type NanoidLib from 'nanoid';

let _lib: typeof NanoidLib;

/**
 * Wrapper to import the ESM module into this project
 *
 */
export async function nanoid(size?: number) {
  // Load library
  if (!_lib) {
    _lib = await import('nanoid');
  }

  // Create ID
  return _lib.nanoid(size);
}

src/usage.ts

import { nanoid } from 'lib/nanoid';
async function doingStuff() {
  const id = nanoid();
}

@cstavaru
Copy link

cstavaru commented Feb 7, 2024

Some funny stats from npmjs:

nanoid weekly downloads: 37 million.

v4 and v5 combined combined weekly downloads (ESM): 1.9 million.
v3 weekly downloads (CJS): the rest up to 37 million.

"ESM is the future". Ok, but how many centuries into the future ? :)

@ai
Copy link
Owner

ai commented Feb 7, 2024

@pBread just move your project on ESM. You will have problems with CJS project not only because of Nano ID, but because of all Sandre's packages, etc. Even Vite deprecated CJS API.

Open source is about community work, not about demanding something from people whom you are not paying.

@ai
Copy link
Owner

ai commented Feb 7, 2024

Is there a reason you don't just transpile it w/a microbundle or something similar?

It is exactly what we did in 3.x.

It has three problems:

  1. it increase library size in node_modules size which is against the philosophy of nano-library.
  2. It could not fix all compatibility problems. I still need to process issues from Jest and other edge cases.
  3. Any build step requires more work to maintain the library. Check ChangeLog, some of releases was because build step did something wrong.

@jsardev
Copy link

jsardev commented Feb 7, 2024

lol, this thread keeps going. @ai I admire that you still have the strength to write everyone back 😅

@markhughes
Copy link

Alrighty, I'll fork my own version.

@pBread are you forking nanoid? 3.3.7 was released not too long ago.. 3.x is still fine if you need CJS, and don't want to for whatever reason move to ESM.

..

@ai I admire that you still have the strength to write everyone back 😅

I'm impressed as @jsardev is. So incredibly patient.

@Petersdavis
Copy link

For people coming here because of Jest specifically you can setup a mock for nanoid which worked to solve our issues:
mock.js

jest.mock('nanoid', () => {
  return { nanoid: () => '1234' };
});

and then call it in global setup:
jest.config.js

{
  ...
  setupFiles:["./mock.js"]
};

@ai
Copy link
Owner

ai commented Apr 25, 2024

Node.js 22 allowed to require() ESM dependencies (like nanoid@4).

Just run your app with experimental-require-module flag:

node --experimental-require-module app.js

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests