It makes me wonder why Deno [1] still seems to be such a niche choice. Most of these headaches just go away.
Does anyone here prefer Deno for new projects? And if not, why?
[1] And Bun, although that's much newer.
It makes me wonder why Deno [1] still seems to be such a niche choice. Most of these headaches just go away.
Does anyone here prefer Deno for new projects? And if not, why?
[1] And Bun, although that's much newer.
I wouldn't necessarily suggest that a newbie programmer go right to Deno yet because today you still have to be prepared to deal with some differences and quirks.
But here is why I like Deno:
- Typescript pretty much Just Works (TM) out of the box without having to think about it
- More web/browser APIs right out of the box with less Node-specific weirdness. Anything that is Deno-specific (such as anything that lives on the Deno global) is, in my opinion, better designed than Node's APIs.
- Requiring file extensions in import specifiers makes total sense to me. Some people think this is stupid, but I see no reason not to make them actual file paths and not this sort of pseudo file path that omits the extension.
- I like how Deno can bundle your application into a single executable.
- Testing framework and linter are built right in. Which is great because, let's face it, most of us have been using such things for a very long time now.
- Being able to pull in modules from the web without NPM is fantastic.
- Node.js and NPM compatibility has gotten way better recently.
- Binary data is handled as Uint8Array rather than using a non-standard Buffer like in Node. Makes total sense. Skip the middle-man and just give me the bytes in a widely compatible form.
- Granular security with strict permissions by default is really nice. Sometimes I do want to import a module but then have a guarantee that third-party code won't phone home. It's also flexible enough that you can allow your own code to reach your own domains but then some module you import from elsewhere doesn't send data to some other domain. I'd still choose to not use such modules, but it's good that you can mitigate the risk of malicious code without having to do anything.
And sure, Node has improved a lot since the inception of Deno and will continue to improve. It can probably do some of these things and may end up having more parity with Deno. I don't think that Node is bad. I still use Node, primarily at work, and in cases where a package has maintainers that refuse to support Deno (ex. Playwright).
I would highly advise any startup considering using them to reconsider. You don't want your business to being running into rough edges all day. You don't want to be reinventing things all day.
They're fun, and especially deno is really fun. It feels more like go, where you control everything.
But they're still not nearly as productive as node
That said, most of my Deno projects have been fairly basic, so I'm curious if there's a point at which the early wins give way to hidden pain points.
import {} from "./mod.js"
You have to write: import {} from "./mod.ts"
ESbuild doesn't transform source imports. Thus, by transpiling your code using ESbuild, you get an erroneous import that leads to a runtime error in browsers and Node. The case is worse for TypeScript, because it refuses to tarnspile this code.By the way, bundling with ESbuild is possible, however when you write a library you generally want to transpile the code, not to bundle it.
import {} from "./mod“;
and we bundle before running. Maybe that explains it.TSC recently added a flag that allows “.ts” imports too.
Yes, ESbuild correctly resolves the path, however it doesn't rewrite the import path. Thus, you end with a javascript file that tries to import a typescript file (this leads to a runtime error in the browser and Node).
> TSC recently added a flag that allows “.ts” imports too.
For type-checking only. You cannot emit code when using `ts` extension.
Is there a good use case where you wouldn't want to bundle TS code?
It seems to me that you either want to execute it directly (via Deno / Bun / ts-node / etc) or bundle it.
Even if you're publishing an NPM package, bundling rather than publishing individual generated .js files works well. You can either bundle your dependencies or leave them unbundled, both work just fine.
If you publish your .ts files, people can import those directly. In my experience that works much better in Visual Studio Code than importing the .js files.
Transpiling instead of bundling avoids some pitfalls. Just to cite one that comes to mind: If your library has a file`a.ts` importing a file `b.ts` including the statement `export * as X from "c.js"`, you could end up with a bundled file that includes an object `X` with the exported elements of `c.js`. This prevents tree-shaking when you bundle applications that use this library.
Transpiling (or just publishing js source files if you don't use TypeScript), also allows a better debugging experience (without relying on source map).
Another point: it is currently not possible to bundle TypeScript declaration files with a regular bundle. If you bundle your sources, you end with a distribution folder with a bundled file and a myriad of lonely declaration files. This is ugly and I am not sure if TypeScript is happy with that?
However, bundling offer also some advantages compared to transpiling: the publication size is smaller, you have less compatibility issues with Deno. Maybe I will switch to bundling my libraries if it doesn't reduce optimization when bundling an application, and when bundling declarations files will be available among the bundlers.
> If you publish your .ts files, people can import those directly. In my experience that works much better in Visual Studio Code than importing the .js files.
Do you know some projects which publish their ts sources?
First, my personal choice is not to use TypeScript. For me it just adds a layer of complexity that adds very little. That I am a sole developer certainly is a factor in that decision. And history. I worked with Java for a long time, with all the safety it provides, only to find that PHP and JavaScript programmers could ship in 1/4 the time with the same level of functionality. I find that passing named parameters: `foo({animal: "duck"})` makes my plain old javascript much more robust, with very little cost.
So strike #1 against Deno is that it puts typescript much more in the foreground.
Strike #2 is that Node works. Not because it is right, but because services make sure they work with node. They don't put the same effort into making things work with Deno.
I needed to write code using Deno that talked to a Digital Ocean managed Postgres database. I spent three days. Then I decided not to use Deno. Was this Deno's fault? No. But if you need to get things done and one in 1000 of those things works in Node but not in Deno, then the choice is straight forward.
I'm not saying these are good reasons, but I did try Deno and wanted it to work.
If you have specific issues with ARM, I'm certainly interested in fixing those. I don't have any timeline for when we'll add Linux ARM as a binary release target but I'm happy to ensure any ARM-only bugs get the proper attention.
Thats the use case I have in mind to cut costs
As long as your ARM OS is 64-bit, Deno should function properly. 32-bit _might_ be supported, but TBH we don't do any testing of those configurations as far as I'm aware.
deno: Mach-O 64-bit executable arm64
...also haven't experienced any problems so far....when installing via homebrew on Mac you get 3 more files which look like shell-completion definitions:
bin/deno
etc/bash_completion.d/deno
share/fish/vendor_completions.d/deno
share/zsh/site-functions/_deno