Deno is great, but not quite there yet
Deno 2 was finally released this week and makes a ton of objective improvements over Deno 1, but it's... still not quite there yet. It feels like the Deno team now tends to prioritize venture capital requests rather than staying true to the original purpose of Deno: to improve on the original Node runtime. As someone who uses Deno all the time for side projects and prototypes[1], I would like to state some criticisms in hopes that someone from the Deno team will listen to my feedback. Don't get me wrong - I love Deno. But there are so many improvements that need to be made before I will feel comfortable recommending Deno over the competition (Node, Bun).
Criticisms of Deno ¶
Better Web API Compatibility ¶
One of Deno's major selling points over Node for me is its adherence to implementing the latest web APIs. That means you can write JavaScript code and execute it both in the browser and the Deno runtime without worrying about API compatibility.
// this works with `Deno run` and in browser consoles!
console.log(globalThis.crypto.randomUUID())
However, there's still a lot of room for improvement. Some APIs still lag behind in support. I wish the Deno team would prioritize supporting these APIs rather than making new products like Deno KV. You know it's bad when Opera has better API support than you.
Here are some examples of Web APIs I wish had better method support (as of Oct 12, 2024):
Better Performance ¶
Deno boasts amazing performance over Node. While it's true that Deno is more performant, I think it's a pretty low bar to be faster than Node (no offense to the Node devs). Bun is another alternative which blows all the competition out of the water with their performance. Some commands with a cold cache can feel extremely slow. You would think it would be significantly faster considering it's written in a faster language than Node (Rust) and uses Rusty V8.
To be completely fair to the Deno team, it sounds like that's something they plan to prioritize in the coming months.
deno install is 15% faster than npm with a cold cache, and 90% faster with a hot cache. We’re already exceptionally fast here, but expect more improvements, especially in cold cache scenarios, in the coming weeks.
Source
NPM Dependency Vendoring ¶
Deno allows you to vendor project dependencies very easily with "vendor": true
but this only pertains to URL imports and JSR packages, not NPM packages. I understand not wanting to prioritize Node or NPM compatibility but lacking NPM vendor support means that only pure Deno applications can be vendored. That rules out virtually every large application. It's not viable to expect every NPM package to have a Deno/JSR alternative.
If you really need vendoring, you can work around this by importing NPM packages from a public ESM CDN like JSDelivr but it's far from ideal.
import markdownIt from "npm:markdown-it"; // cannot be vendored
import markdownIt from "https://cdn.jsdelivr.net/npm/markdown-it@14.1.0/+esm"; // can be vendored
Statically-Linked Binaries ¶
deno compile
has yet to support creating statically-linked binaries. There's not a huge incentive to compile binaries without this as it breaks on every non-standard system.
deno compile --output output input.js
# Compile file:///home/sam/input.js to output
./output
# Could not start dynamically linked executable: ./output
# NixOS cannot run dynamically linked executables intended for generic
# linux environments out of the box. For more information, see:
# https://nix.dev/permalink/stub-ld
It also doesn't support compiling with musl so there's no Alpine support.
deno compile --output output input.js
# Download https://dl.deno.land/release/v1.43.5/denort-x86_64-alpine-linux-musl.zip
# Download could not be found, aborting
Custom Lint Rules ¶
Deno only supports a specific subset of code linting rules that eslint provides. It also doesn't allow you to write your own custom rules and load them. There's a Github discussion for a plugin system, but it doesn't sound like it is being prioritized.
JSR Github Interop ¶
JSR only works properly if you fully commit to Github. Without a Github account you can't publish packages, and without hosting your packages on Github you can't publish provenance. There's no incentive for anyone using an open source code forge to use a Github account only to publish packages.
I think they should decouple JSR from Github and allow email-password (or passkey) accounts to publish packages. There's also better ways of signing package versions. That's what PGP is for.
Praises of Deno ¶
To prove I'm really a fan of Deno and not just ragging on it, here are some features I absolutely love about Deno.
Zero Configuration TypeScript support ¶
Imagine a Node project with free automatic TypeScript support. It feels amazing to be able to write a TS file and execute it directly without downloading a bundler or including a compilation step. Deno has first-class TypeScript support with absolutely zero configuration required. Node has an experimental flag to strip types but it's still far behind Deno.
Import Maps and JSR. ¶
JSR and import maps make it super user-friendly to import new packages with built-in documentation and type support. Due to the nature of import maps, it's also easy to mock out dependencies if needed:
{
"imports": {
"https://deno.land/x/lume@v2.3.0/": "./mocks/lume"
}
}
JSR in itself is an objective upgrade to a lot of the flaws of NPM with its documentation, scoring, and immutability. I really appreciate how the Deno team is trying to combat supply chain attacks.
LSP ¶
Deno comes with a built-in LSP that combines linting and formatting. The LSP also formats HTML, CSS, YAML, JSON, and all the CSS/JSON variants too. There's no need to have a custom external eslint/prettier configuration in Deno.
ESM only ¶
Deno only supports ESM. This reduces a whole layer of commonjs complexity nonsense that still exists in Node. Deno also uses proper package exports in JSR. You don't need to worry at all about module resolution or making sure libraries are packaged properly.
Conclusion ¶
I love using Deno in my projects. While it's not quite perfect yet, I'm hopeful the Deno team can continue to improve the software and truly replace Node. Thanks for all of your hard work!
Heck, this website you're reading is generated with Deno. ↩︎