npm compatibility is huge for Deno. It is basically the one major drawback to Deno, which gets hopefully fixed with this feature. It also looks like this compatibility layer is implemented transparently in the existing module management, which is a big bonus. Nobody wants to deal with node_modules anymore when working with Deno for an extended period, just love to see this.
Core features for npm compatibility though (like implementing most of the npm api, including require(), and its special globals) has been making progress for a long time.
There is even a near complete project to support Node's native api (which bun also supports): https://github.com/denoland/deno/pull/13633
Relative to the the existing node compat efforts, the url import (and accompanying package download code) will be fairly small. The most difficult part is probably the extra stuff that node throws in the global namespace. How to handle that without having to pollute the global namespace for all programs (even those that do not import from node) is unclear.
Ideally these globals would be visible only from code in modules imported from npm. But the spec does not really allow for this unless the npm code is loaded in a different realm, but cross realm code causes a lot of headaches, which could only be avoided by having the realms share most globals and intrinsics (and sharing intrisics is not allowed by the spec).
There may be some other way to hack this into working, or perhaps programs with such imports that actually use NPM specific objects will need to be run with the "--compat" flag. It is really unclear at the moment.
Like you said, don't know if Bun had an influence on the timing of this announcement, but great to see innovation in the JS server space. Kudos to both the Deno and Bun folks!
BunJS does of course have a slightly different use case, packages or apps that still need to make use of Node APIs. I can see a future where we say "if you have an old Node app, you can run it on BunJS with a codemod and get an X% perf boost for free", as well as "if you are starting a new project, just go with Deno because there's less BS to think about".
Don't personally know anyone who is treating Bun as anything more than a curiosity.
Any thoughts on speed reliability concerns comparing the two?
NPM is a giant pain point, and I suggest that Deno and a lot of other people want to move on from it.
But the gravity is just too much.
This seems like an acceptance that moving on simply won't happen. The existing ecosystem is too big and too powerful to be ignored. If I were a particularly cynical person I'd also point to Deno taking on millions in VC funding - once you've done that you can't be content to create a perfect, gleaming sandbox. You have to bring in money.
When contemplating how I might do it, I came up with centralised reexport, a file deps.ts containing:
export express from "npm:express@5";
This would basically stand in for the dependencies object in package.json.So then I looked up the docs and found https://deno.land/manual/linking_to_external_code#it-seems-u... and was amused to find the same solution, even down to the file name “deps.ts”!
Is this how people tend to work with Deno?
I see it also supports import maps, https://deno.land/manual/linking_to_external_code/import_map..., which could readily solve the problem too. Do people use that?
In fairness, the two examples, Deno and Go, are successful projects, so maybe it's not a bad initial strategy.
I'm very interested in how packages will manage runtime support in the future. Right now we are seeing an explosion of JavaScript runtimes from Cloudflare Workers to Bun, all with sightly different APIs. I wonder if there will be an easy way to get cross-runtime support without it being much extra work for library authors.
Right now, there has already been conflict with some packages being browser-only and some being node-only. I feel like there needs to be a better solution than the one we have now.
> There will be no node_modules folder, no npm install; the packages will be automatically downloaded in the Deno cache.
My understanding of deno's package system (see https://deno.land/manual/linking_to_external_code#it-seems-u...), is that basically, at compile time it will go and fetch external URLs and cache those files locally. So this change basically makes it so your import:
> import { assert } from "https://deno.land/std@0.152.0/testing/asserts.ts";
Is magically generated from npm when you do this instead:
> import { assert } from "npm:testing@2.0.1";
Ok cool. Whatever.
...surely this isn't the actual problem?
There seem to be certain pretty fundamental problems:
- not all npm packages are typescript
- a package is not just an 'assert.ts' file, it's often an amalgamation (eg. using rollup)
- a package often has many dependencies
- a package may use the node API, that deno doesn't have (it has a more-or-less compatibility mode, see 'differences that cannot be overcome' -> https://deno.land/manual/node)
So bluntly, how on earth is this going to work?
I mean, I'm a fan, the folk working on Deno are smart and motivated, and if it works, I'm more 'wow' than 'I don't believe it'... but I'm very surprised to see:
> the vast majority of npm packages work in Deno within the next three months
That seems... ambitious.
I can't see how the approach is really sustainable, given that basically, it means 'anything node supports we have to support to'; doesn't that mean you're forever playing catchup and 'doesn't quite work'?
How is vendoring going to work without a package lock file? Doesn't this just mean you've reimplemented npm and you'll forever be playing catchup to the various npm features that are required to make packages work?
That, and the emphasis on speed (esp quotes like "We aren't optimizing for a handful of edge cases, but for overall real world performance") makes me wonder if Bun is lighting a fire under them a bit. It's still a long way from catching up, but it's been closing the gap at a blistering pace and getting enormous amounts of hype. The more competition the better.
Exciting times
It almost sounds like I could write a self-contained deno command-line "app" that does this. Does that seem right (for those that know better)?
This is really huge and will be a huge boost to the Deno ecosystem. On the other hand, I quite enjoyed that it wasn't jacked into NPM. There were reasonable alternatives like https://jspm.org/. This is a big swing at Node and I'll be watching with maximum curiosity.
As an aside, the only thing preventing me from adopting Deno as my daily driver has been the lack of AWS Lambda support (requiring a lambda layer, slowing down cold starts). Would be great if they could leverage connections and advocate for native AWS support.
Furthermore, will it support unifying transitive dependency versions to minimize bundle sizes?
It's also interesting to note how the tone changes after receiving funding. May just be a coincidence, but this looks like a reactionary jab back at Bun, which is barely out of the gate.
I'm excited to see this, and I'm sure they'll work this out, but I sure hope I don't have to keep dependency versions in sync across all of my import statements. I don't have much love for package.json and node_modules, but it is nice to have one source-of-truth for all the dependencies of a project.
I'm not rewriting my work so someone can have fun playing with VC money and abandon mature software.
Supporting npm is one big step forward, but without a package-lock.json that locks all child dependencies, it’d be a nightmare using the new compatibility in production
They are not clear if you need to have npm installed or not for this to work. I sincerely hope not - if it requires a locally-installed npm then they've shat the bed I think... that would be a major turn-off for me.
Can't say I've ever been concerned by the performance of Deno, but looking forward to seeing this playout anyway since faster is always nice to have.
I get it, I understand it, but it is depressing to know that we're going to be dealing with horribly ridden legacy NPM code for the next 800 years.
A lot of the code on NPM is just bad. And now we're going to keep this legacy of just, bad JavaScript .
This is why I prefer dart and flutter for making mobile apps. Over react native.
For reference: https://news.ycombinator.com/item?id=32457587
Btw, I like where it's going but I find it quite sad that there is no official linux ARM64 support yet - which means I can't try to use it on AWS lambda for example.
Can this really be right? What is the number for Nodejs?
But while "the vast majority" of npm packages don't require a gyp build step for native addons, some of those modules are pretty important, and I see no indication in the announcement that they're also going to be implementing the Node C API or the gyp build process.
Right now I'm working with a machine learning project, and XGBoost [0] is a direct Node.js extension [1] through the binary interface.
So this does bring things a step closer to being generally usable, but there are still significant roadblocks.
A WebAssembly build of XGBoost could work with Deno, but aside from some guy's unsupported side project/proof-of-concept for use in a browser, I'm not seeing an XGBoost WebAssembly build. And generally when deploying something like a machine learning model I'd rather use well-supported tools than to need to dive into the rabbit hole of maintaining my own.
And yes, XGBoost will likely eventually have that kind of support for Deno, but then the next bleeding-edge project will come along and only support Node.
Even assuming Deno eventually hits a tipping point in popularity where everyone wants to release Node _and_ Deno support in their bleeding-edge projects, there are still things that I miss from package.json that don't seem to exist in the Deno ecosystem.
Things like the "scripts" block: A nice centralized place to find all of the things that need to be done to a project, plus auto-run script entries that can trigger when a project is installed. And inheritable, overridable dependency maps (see the yarn "resolutions" block).
I'd love to jump into Deno, but I think there has been far too much "baby thrown out with the bathwater" to its design. It's the classic development problem of looking at a system and seeing a ton of complexity, but not really understanding that all of that complexity was there for a reason. Maybe when it re-evolves 80% of Node's and npm's features I'll be convinced to make the jump. I'm a huge TypeScript fan after all. But it still strikes me as a violation of "As simple as possible, but no simpler."
[0] XGBoost is a _very_ promising approach to machine learning, training models much faster and with much more accuracy than traditional approaches.
I still don't understand why they have this feature and still consider themselves security focused.
Do we know what will differentiate the 10-20% of packages that won’t work?
curious what kind of npm packages won't be supported in Deno
I feel unease reading untestable claims (with no numbers) about future releases. I'm made more uneasy by the fact that this is the second bullet point of the main tl;dr. It makes me wonder, what are the organizational incentives driving such a publication?