mathiasbynens / punycode.js

A robust Punycode converter that fully complies to RFC 3492 and RFC 5891.
https://mths.be/punycode
MIT License
1.59k stars 159 forks source link

Naming collision when installing punycode via npm #79

Open pdehaan opened 6 years ago

pdehaan commented 6 years ago

I'm using Node 9.7.1, and have punycode@2.1.0 installed (via $ npm i punycode -S), but when I try and log out the punycode.version variable, I always seem to get "2.0.0", so I think my machine is still using the default/bundled/deprecated version of https://nodejs.org/api/punycode.html

How can you install this module from npm and use it in Node 8+ without it using the built-in version of the punycode module? It looks like I can use the npm version if I do something like require("./node_modules/punycode"), but that feels wrong.

$ node -e "console.log(require('punycode').version)" # 2.0.0
$ node -e "console.log(require('./node_modules/punycode').version)" # 2.1.0
$ node --version # v9.7.1

$ node -e "console.log(require.resolve('punycode'))" # punycode
$ node -e "console.log(require.resolve('./node_modules/punycode'))" # /Users/pdehaan/dev/tmp/node_modules/punycode/punycode.js
KaiSchwarz-cnic commented 6 years ago

Maybe package-lock.json or a npm-shrinkwarp.json file helps here. Deeper read: https://docs.npmjs.com/files/package-locks But really not sure if that helps..

mathiasbynens commented 6 years ago

IIRC there was a better way of preferring an npm-installed module over a Node-built-in module, although maybe I was dreaming. @zkat, do you know?

zkat commented 6 years ago

This is literally impossible and unlikely to ever change. It is the first alternative in Node's module lookup algorithm, and so there's.... basically no actual way to do this besides referencing the module by path.

I would be tremendously surprised if this -ever- worked -- you might consider using a @scope for it, or simply publishing it as punycode.js (which is available! Get it while it's hot!).

zkat commented 6 years ago

Of course, the other alternative is to make Node's built-in punycode module do a path-based lookup in a project's current dependencies, but it ain't pretty to do that, imo. I think it's important to continue enshrining node built-ins as special without getting into weird bypassy shenanigans like that? It's a case you can make with them, though, as I have no say in what their decision would be ;)

mathiasbynens commented 6 years ago

Thank you, @zkat!

mathiasbynens commented 6 years ago

I went with @zkat’s suggestion to publish a copy as punycode.js, so @pdehaan you can now use npm install punycode.js and require('punycode.js') as a workaround.

vladikoff commented 6 years ago

Thanks @mathiasbynens :)

pdehaan commented 6 years ago

Also, for my own future reference and general interest, I randomly spotted this gem in the eslint-plugin-node node/no-deprecated-api docs while closing some tabs:

⚠️ Note that userland modules don't hide core modules. For example, require("punycode") still imports the deprecated core module even if you executed npm install punycode. Use require("punycode/") to import userland modules rather than core modules.

$ node -e "console.log(require('punycode').version)" # 2.0.0
$ node -e "console.log(require('punycode/').version)" # 2.1.0
vladikoff commented 6 years ago

@pdehaan cool hacks!

mathiasbynens commented 6 years ago

Ooh, that may have been the workaround I was trying to remember! I like require('punycode/') much better than having a separate package.

pdehaan commented 6 years ago

Not that this is a democracy, but I like the new package name approach much better. It's a lot more obvious what's happening, and you wouldn't have to try explaining the odd looking trailing slash in the require statement. It always feels weird to me that you can publish npm modules which have the same name as core Node modules (a la "fs", "path", "os", "crypto", etc). Seems super confusing, and the number of times I've seen people include "path" in their package.json is scary.

michael-letcher commented 6 years ago

@mathiasbynens Can punycode.js package be updated to 2.1.1 as well?

As I agree with @pdehaan as why require the use of a "hack" to be able to use the package.