Open g012 opened 2 years ago
Attempting to change the module system (compilerOptions.module
) from CommonJS
to ESNext
in tsconfig.json. doesn't work in Node.
It now appears all Node users will have to BOTH manually roll back to v3.3.4
AND begin looking for a replacement for this library as CommonJS has been permanently abandoned in v4
.
Too bad it's so easy to accidentally or silently upgrade nano versions and break your entire build, as I did.
Too bad it's so easy to accidentally or silently upgrade nano versions and break your entire build, as I did.
Luckily its just as easy to rollback to v3 and stick with that
After all the time wasted chasing this, and after taking steps to attempt to warn all our developers that this library (and in our case, ONLY this library) can never be updated, you're right. It was pretty easy typing in a different version number. Of course, difficulty in rolling back was never the complaint.
this is terrible, any alternatives to this lib, not doing such bullshit? Why do good libraries like husky and this one always have to fuck it up somehow?
Why do good libraries like husky and this one always have to fuck it up somehow?
Because moving to ESM is a global trend in JS ecosystem. It is better to join it.
Are you aware that all packages dependent on your library are forced to adapt (right here, right now)? Isn't it better to add a build task that also generates the common js before publishing to npm?
Isn't it better to add a build task that also generates the common js before publishing to npm?
We have it for 3.x release, and it took a lot of time to maintain and have problem for some edge cases.
this is terrible, any alternatives to this lib, not doing such bullshit? Why do good libraries like husky and this one always have to fuck it up somehow?
agreed, this whole shift is zero benefit if you're typescript anyway and endless pain.
I use cuid on another react native project. I think it might have some similar ESM bs issues tho https://www.npmjs.com/package/cuid
@ai I find your reasoning for not dual publishing unconvincing.
Export maps are part of the esm transition so your exact same reasoning for pushing esm and forcing the ecosystem to migrate applies there too. They are also far more supported than just plain old esm.
esbuild takes like some 10ms to build twice. And there’s tons of tools to use node register with that are trivial to use if you somehow are forced to import just esm.
And any analyzer worth its weight will need to support export maps to do so.
I’ve gone the dual publishing route and had no complains from tons of users so far. If you do it properly it supports both without and hiccups across all sorts of tools. And you avoid giant threads like this on your project.
The only downside is node_modules being slightly bigger.
The only downside is node_modules being slightly bigger.
The downside is maintaince from the repository owner.
I do not have enough funding from my open source to spend extra time for both ESM and CJS versions.
Fair. Not critiquing just thought I’d add perspective as someone doing it. Something like tsup or just a small script that runs esbuild twice typically works and can be added as a pre publish or commit hook.
just hope nobody is using nano in another package as it will suddenly blow up
This isn't true, unless you explicitly specify the dependency version as *
.
Something like tsup or just a small script that runs esbuild twice typically works and can be added as a pre publish or commit hook.
Just run esbuild
will not work.
I created dual-publish
and just check how many edge cases maintainer have to think about (Node, webpack, Node + TS, webpack + ts, esbuild, rollup, Parcel).
Maintaining cost is not when everything is working, but when it goes to edge cases.
And if you keep esm by default but allow to explicitly import from nanoid/cjs
? At least I'd be able to alias in that case. Using nanoid in most cases works ok, but setting up jest to allow for certain packages to use esm is a pita in monorepos. Setting up an alias is much easier.
@bkniffler what’s even easier is just using nanoid@3
And if you keep esm by default but allow to explicitly import from nanoid/cjs?
Maintaince cost will be again too big (for the feedback I have from the community).
For pnpm users who frequently use pnpm update --latest
, they just added a configuration option for pnpm.updateConfig.ignoreDependencies
in v7.13.0:
pnpm add nanoid@3
// package.json
{
"pnpm": {
"updateConfig": {
"ignoreDependencies": ["nanoid"]
}
}
}
@michaelhays it’s nice that this exists, but this probably ignores 3.x
releases as well. I doubt there’s much that can go catastrophically wrong in nanoid
, but it’s something one should be aware of.
If you're coming here from React, v18 shipped the useId
hook that might work for you.
The entitlement from some of the assholes in this thread is unbelievable. I'm running into this issue myself and yes, it's causing some minor pain. But it would never occur to me to yell at the maintainer and demand changes. Show some fucking respect people.
The only downside is node_modules being slightly bigger.
The downside is maintaince from the repository owner.
I do not have enough funding from my open source to spend extra time for both ESM and CJS versions.
Would you like me to create a PR with the build script for both ESM and CJS versions?
Would you like me to create a PR with the build script for both ESM and CJS versions?
PR is not help. It will take me a week to then fix all possible issues and then I will spend a day every week answering people with rare Jest edge case.
I already wrote dual-publish
build script (it is not so easy btw) but in some moment I found that it is just impossible to cover all edge cases.
nanoid and express are my favorite packages of all time.
If this arm-chair comment is not useful, please excuse me. Possibly the build process could be simplified to enable cjs and esm. As mentioned here, If nanoid exports a single default, a cjs variant can be generated with sed.
cp nanoid.js nanoid.cjs && sed -i 's/export default/module.exports =/' nanoid.cjs
After form-urlencoded began using this approach, cjs/esm issues went away.
In the previous ticket, you did not want to try this approach because of risks. Since risks are already incurred, maybe the approach could be reconsidered.
same here
same issue
I have the same problem. I want to use the latest version available but it doesn't work :/
downgrading to version 3.3.4 worked for me, if it can help
Understand and respect the author's choice, even if I can downgrade to v3, I probably won't use this product again. Hope to find a good replacement soon.
💩
To tell a joke, the software forces the platform to support his software to solve the problems encountered by users.
I found the author to be a double standard person. I hope that the "nanoid" package will no longer appear in my software, especially Node-based backend projects. At least most of the packages I use are built using TS, and support will gradually increase with platform upgrades. These packages developed using TS make my work happy. nanoid makes me desperate to find a replacement.
So much hate, disrespect and general crying while you can just downgrade 1 version and have (almost) the exact same thing, as the only thing that you'd benefit from v4 is the reduced package size - which is actually a few bytes. There are no security fixes, no additional features that you'll miss. What's the point?
And that's not all! This repository is under MIT license so you can just grab it and have your own version if you rely so much on it. You can apply any security fixes that would come up to v4. And there's more! The package is basically a single 85 LOC file which you could adjust to do whatever you want it to do.
Unbelievable 🙄
Reverting back to 3.* works, however, I always update my packages to the latest version, and don't want to keep this one outdated. You can import the package using dynamic import and it works for version 4.0.0. Put this code in constructor or as part of your app's initialization.
(async () => {
const module = await (eval(`import('nanoid')`) as Promise<any>);
const nanoid = module?.nanoid;
console.log(nanoid && nanoid(10));
})();
In my case, I just needed to generated a random code. So I just did this instead:
const crypto = require('crypto');
function generateRandomCode(length, characterSet) {
let code = '';
for (let i = 0; i < length; i++) {
const randomIndex = crypto.randomBytes(1)[0] % characterSet.length;
code += characterSet[randomIndex];
}
return code;
}
// Example usage:
const characterSet = '349ACEFHKLMNPRTWXY';
const codeLength = 5;
const randomCode = generateRandomCode(codeLength, characterSet);
console.log(randomCode); // prints a random code of length 5
the same problem in sequelize seeder esm script, try to use follow replace it.
import { v4 as uuid } from 'uuid'
const nanoid = (size) => {
return uuid().replace(/-/g, '').slice(0, size)
}
I was using this library for educational purposes to generate random IDs for a simple file-based database. Not anymore, I guess. I will just move to crypto.randomUUID()
which is already built into Node.js.
Use 3.3.4 if you need CommonJS support. Use 4.0.0 if you need ESM support.
Removed CommonJS support. Nano ID 4 will work only with ESM applications. We will support 3.x branch with CommonJS for users who can’t migrate to ESM.
I was using this library for educational purposes to generate random IDs for a simple file-based database. Not anymore, I guess. I will just move to
crypto.randomUUID()
which is already built into Node.js.
Basically, I did the same as built-in would make more sense since may be a little more supportive.
Dual ESM/CJS packages is not a good thing. As a developer of dual-publish I can say it without a doubt.
- You need to duplicate every file in npm package which increase
node_modules
size.
Since the files are only on the file system, I don't see this as a problem, since when bundling with webpack, rollup etc for a nuxt, next, svelte, ... app only the corresponding module file ( cjs or esm ) is included in the bundle.
- 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).
Yes, Jest causes problems more often, but I think you can take that into account before you start backporting changes.
- Dual packages requires extra build step (like
dual-publish
orbabel
). With ESM-only you can publish your repository directly.
But cjs, can be used in both a cjs and esm ecosystem. This is not the case with esm for top level imports.
- It also make more complex another tools. For instance, Size Limit will require extra plugin.
- 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.
True
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.
You are absolutely right, but I think the step, one should go only if e.g. NodeJs Esm no longer runs in expermintal mode.
Things will only have a chance of moving to ESM when nodejs starts enforcing it (which might as well be eternity), until then there's just not enough pressure to do it. Nobody is going to try and update/replace countless mini-libraries down the depedency chain just because of some developer activism. And that's all this is. Everyone has the right to publish open source libraries that output to only ESM or not, but CJS is here to stay and that's the reality.
To those who really don't want to use v3, you have two options:
@jpike88 I see it exactly the same way
But cjs, can be used in both a cjs and esm ecosystem. This is not the case with esm for top level imports.
CJS can’t be used as module from URL:
import { nanoid } from 'https://cdn.jsdelivr.net/npm/nanoid/nanoid.js'
Also CJS has problems with named exports in some environments.
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.
This should be front page on the readme because this is wasting a lot of peoples time.
@sugoidesune it is in Install
section of docs
@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.
@eezing this is why I moved from Jest
@ai what did you move to? is there some other testing framework that works with nanoid ?
thats worked for me :
npm uninstall nanoid
npm install nanoid@3.3.4
@dcsan not ai, but want to share this opinion after using different test frameworks,
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!
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 !