Reputation: 9451
I'm using the npm module punycode
in my Angular project.
VsCode tells me it's deprecated and https://nodejs.org/api/punycode.html#punycode_punycode
confirms:
The version of the punycode module bundled in Node.js is being deprecated. In a future major version of Node.js this module will be removed. Users currently depending on the punycode module should switch to using the userland-provided Punycode.js module instead.
The suggestion is to switch to the 'userland-provided' module. What is that?
There is a link to https://github.com/mathiasbynens/punycode.js and I tried including that in my package.json instead of 'punycode' and I get the same error.
Upvotes: 212
Views: 384561
Reputation: 1730
Recently I faced this same issue.
I highly recommend you use the LTS(long term support) version of the node.
You can validate the version here: https://nodejs.org/en
so then in your command line you should perform:
$nvm install --lts
$nvm use --lts
This solves the problem, because makes you use the most tested and approved version.
If I use the version with latest features (actually 21.5.0 at time of writing instead of 20.0.8) I will face the problem reported here. There is an issue open in github to solve it by the way.
You can see more details here: https://github.com/yarnpkg/yarn/issues/9005
Upvotes: 134
Reputation: 4111
The issue is that Node.js has its own punycode
module, which is deprecated starting with Node.js 22. The recommendation is to use a replacement punycode module from npm instead, which is not maintained by the Node.js crew. The most prominent replacement punycode
package on npm is called punycode
as well, and it will be pulled into a Node.js project, if packages.json
contains a dependency on punycode
. This mean any package that depends on punycode
tries do the right thing. This does not mean, every package that depends on punycode
actually does the right thing.
npm ls punycode
, as suggested by some answers, lists packages with a declared dependency on "the userland-provided Punycode.js module", so it will find all packages that already comply with the migration path for the deprecation of the punycode
module as supplied with Node.js. On the other hand, packages that just rely on a module named punycode
being unconditionally available, because that module is part of the core Node.js runtime environment (which is the punycode
module that is deprecated) are not found by this command.
The next key point is the behaviour of require("punycode")
. This statements imports the "first module named punycode the JavaScript runtime stumbles upon". Most prominently, as the deprecated punycode
module provided with Node.js still is present, it will be found first, even if a punycode
package from npm is installed as well. So depending on punycode
in pacakges.json
only does half of what you need to do, because that dependency will just cause the punycode package to be downloaded, but not to be used instead of the deprecated punycode
module. The require
statement needs to be re-written in a way that it is unable to pick up the integrated punycode
module and thus needs to resort to the punycode
package inside node_modules
. The recommended way of doing so is replacing require("punycode")
by require("punycode/")
.
In my case, the issue was caused indirectly by jest-environment-jsdom
which depends on jsdom: "^20.0.0"
in the latest "stable" version 29.7.0. This dependency resolves to the latest 20.x version of jsdom, which is 20.0.3. Its packages.json
file references whatwg-url: "^11.0.0"
, which will resolve to 11.0.0, as this is the only 11.x version of whatwg-url
ever released. That package then references tr46: "^3.0.0"
, which resolves to version 3.0.0 of that package, which is a known offender that has already been mentioned in other answers.
Now let's look deeper into this package, though: In packages.json
, the required dependency to download the "userland" aka "3rd party" punycode
package is present, which means this package tries to not use the built-in punycode
support. Nevertheless, it uses the require
statement that will pick up the integrated punycode
support, as long as that one is shipped with Node.js. The require
statement has been fixed with version 4 of tr46, and seems to be the only significant change between version 3.0.0 and 4.0.0 except for bumping dependency versions.
So what does it mean for readers of this question? For me, the take-aways are:
punycode
.npm ls punycode
.jest-environment-jsdom@latest
(29.7.0 at the time of writing this post) -> jsdom@20.*
(20.0.3 at the time of writing this post) -> whatwg-url@11.*
(11.0.0 at the time of writing this post) would issue a patch or minor release that slightly bumps dependencies, we would get [email protected]
or newer which fixes the issue (although for interop reasons, bumping the dependencies to a new major version is likely not allowed in a minor or patch version according to semver). Having a [email protected]
with the punycode fix would help as well, and most likely be the smartest solution possible. Makes me wonder whether you can npm link
a "private fork" of tr46 at a self-deployed 3.0.1.npm --node-options=--trace-deprecation run test
did help me find the issue. (see below this list)require("punycode")
or require('punycode')
inside node_modules
is also a way to find violators.punycode
module, require("punycode")
will no longer use that module instead of a "userland" module.require("punycode")
statement. For example, to work around the issue in [email protected], I added "overrides": { "[email protected]": "4.0.0"}
to packages.json
. As I understand it, although the major version has been bumped, it should work just fine in dependency chains created for major version 3.(node:....) [DEP0040] DeprecationWarning: The `punycode` module is deprecated. Please use a userland alternative instead,
at node:punycode:3:9
at BuiltinModule.compileForInteralLoader (node:internal/bootstrap/ream:399:7)
....
at require (node:internal/modules/helpers:141:16)
at Object.<anonymous> (<workdir>/node_modules/tr46/index.js:3:18)
Note that the whole stack trace is just the internal logic in Node.js that processes the require
statement in tr46/index.js
and doesn't provide any value in diagnosis, just the lowest line points to the issue.
Upvotes: 4
Reputation: 308
If you want to use Node 21 or above (and sooner or later, you will, we all will), the main problem here is that many 3rd party libraries depend on native punycode
and you don't have easy access to them.
Actually, you do have decent access.
See here the solution:
npm install module-alias
Then in your code:
const moduleAlias=require('module-alias')
moduleAlias.addAlias('punyCode', 'punyCode/')
Upvotes: 4
Reputation: 147
You need to install first Punycode. In the console type npm or yarn or 'pnpm i punycode', depending on what you use. Then open Notepad++ and and go to 'Search/Find in Files'. On 'Find what:' write 'require("punycode")' and on 'Replace with' write 'require("punycode/")'. Then press the 'Replace in Files' button and everything should be ok now.
Upvotes: -2
Reputation: 626
This warning just means that one of your project dependencies is using the punycode
module that is deprecated. I fixed the error by following these steps:
npm ls punycode
to see the dependencies using punycode.├─┬ [email protected]
│ └─┬ [email protected]
│ └─┬ [email protected]
│ └─┬ [email protected]
│ └── [email protected] deduped
└─┬ [email protected]
└─┬ [email protected]
└── [email protected]
npm update <package1> <package2> ...
to resolve the warning. In this example, I ran npm update expo expo-dev-client
Upvotes: 53
Reputation: 541
Use npm ls punycode
to find the dependencies that is using punycode
.
In my case, that is ajv
, which is from typescript-eslint/parser
from node_modules/@typescript-eslint/parser
└─┬ [email protected]
└─┬ [email protected]
└── [email protected]
When I look into ajv
and found it's resolved in newer version, I override the version of ajv
by editing package.json
"overrides": {
"ajv": "^8.17.1"
}
npm ls punycode
says there is no dependence anymore.
But in my case, when running the app again, the warning is still there.
By add --trace-deprecation
the compile script, we found other dependencies that is still using punycode
"scripts": {
"compile": "tsc && node --trace-deprecation dist/src/app.js",
}
And found whatwg-url
is the one that is using punycode
.
└─┬ @google-cloud/[email protected]
└─┬ [email protected]
└─┬ [email protected]
└─┬ [email protected]
└─┬ [email protected]
└── [email protected]
When looking into whatwg-url
, the newer version also address the issue.
We update package.json
again
"overrides": {
"ajv": "^8.17.1",
"whatwg-url": "^14.0.0"
}
No warning anymore :)
Upvotes: 29
Reputation: 51
Fixed
As Mentioned at NPM
https://www.npmjs.com/package/punycode#installation
First
Throw VSC Search Bar
You Must Press 3 Points at Right Bottom AND Select ./node_modules IN 'files to include' Text Box
OR Right Click ON node_modules Folder and Select 'Find On Folder'
THEN You Can Replace ALL
require("punycode");
WITH require("punycode/");
AND All Ones with Single Quotes Too
require('punycode');
WITH require('punycode/');
Upvotes: 5
Reputation: 9370
While punycode is deprecated, you can still use it at least for now and bear with the warning. However, to prepare for its future removal, it's still good practice to figure out where it is used and address it before it is removed. It's better to be safe than sorry later.
--trace-deprecation
option to node
. If it's triggered by npx
, run npx
with ----node-options --trace-deprecation
.Upvotes: 9
Reputation: 1837
Frequently, usage of the punycode
module was simply for conversion of a domain name to ASCII, e.g., when MIME-encoding an address.
Yes, the module does a lot more, but commonly, you're just using the toASCII()
function, handing it a domain name. For that, this deprecation, confusion over the magic trailing slash, further confusion when using ESM imports, all ends up being a bit complicated.
If that's the case, then the domainToASCII()
function in the node:url
package might be a simpler way to get your desired result.
Upvotes: 2
Reputation: 101
I also got the message:
(node:14220) [DEP0040] DeprecationWarning: The
punycode
module is deprecated. Please use a userland alternative instead.
I solved it by running npm update ajv
.
AJV stands for Another JSON Schema Validator.
Upvotes: -1
Reputation: 41
From my experience, this solution with ('punycode/') - does not work. It doesn't seem to have any problems with any LTS version, but on anything 21.^ and above - unfortunately not a single hack I've seen - does NOT work (so far). I tried the final LTS version (v20.11.0) this morning and it works.
Upvotes: 3
Reputation: 163
In my case, despite not using punycode directly in my codebase, Nodemailer relies on it. To address this, I implemented a custom script, as detailed in the linked GitHub issue.
If your situation differs, you may need to identify which library is utilizing punycode and apply a similar workaround until an official fix is released. Feel free to share a test case publicly, and I'd be happy to assist you further.
Upvotes: 6