It looks like a good evolutionary improvement over Node.js. However, I have a concern about its security claims. Perhaps someone on the project can allay these concerns.
My brief skimming of its site indicates that its security model is based around the ability to disable, say, network access for whole Deno programs. However, does it allow starting up with network access, allowing a subset of the program to handle it, and then dropping those rights for the rest of the program, _especially_ subdependencies?
A modern Node.js web service will have hundreds, if not thousands, of indirect dependencies. Some network access will be required for at least the Express routing, or an equivalent.
For a Deno equivalent, this would amount to enabling network access for all hundreds of those subdependencies, not reproducing the isolation in capability-based security such as WebAssembly nanoprocesses.
Have I missed something here? That doesn't seem like much of an improvement over Node.js except for very small and contained programs. Yes, Deno's dropping of centralised package repositories and package.json might alleviate this problem _somewhat_, but the same fundamental issue seems to remain.
This prevents dependencies from using call back locations that are outside
the permitted list, preventing much of the nefarious activity they can dream up.
If a dependency needs access to specific resources, it can advertise this fact and the parent module can in turn request this from the user.
Importantly, the user is explicitly aware of these & controls it in an absolute sense, at run time.
The whitelisting looks great. Even with the remaining concerns I raised in the other comment, the ability to whitelist only allowed domains for network connections is a massive step up security-wise, even if they are allowed for the entire program (until revoked globally).
> Importantly, the user is explicitly aware of these & controls it in an absolute sense, at run time.
I mean, I guess I see value there for the use case of "I want to download a script to run locally on my machine" type of thing, but for the most common use of Node, i.e. I'm running a server process, does this really even matter?
That's a good start, supporting the dropping of privileges after performing something on startup.
What about keeping the network allowed in the layer handling, say, inbound HTTP connections, but blocking it in the data access layer or purely computational component?
From what I can see, this doesn't work with global boolean flags in the runtime, instead requiring isolated tasks with whitelisted capabilities passed in, some form of "immutable, set-once, dynamically-scoped capability flags", or something like that.
The problem with the global boolean flag approach is that if any part of a service needs it constantly, the entire program gets it, even obscure subdependencies for generating colour pickers.
Don't get me wrong, it's an incremental improvement over's Node.js blase approach. It's also quite niche to see languages support this feature. E was one of them. There was another newer Python-like language with this too, starting with an `M`, but its name escapes me.
I'd recommend Deno's developers look at E a bit more before committing too much to the platform boolean flag approach. Or I've misunderstood their approach and it actually does more than I'm giving it credit for.
What would be really useful is if only sections of code can be delineated as requiring certain permissions. This way, it's much easier to see what parts of the code do what and also to make sure that users only get prompted for such permissions when the code actually runs.
Also, "promise first" seems to be premature to me. You could have simpler, more stateless async/await without promises: https://www.npmjs.com/package/casync
I'm really curious about whether people think Deno will succeed. Node certainly has its warts, but I feel like with recent improvements in the JS language and Typescript that Deno doesn't really solve problems people have nowadays. I don't think the decoupling from NPM and the dependency management approach (or lack thereof) is really a thing that most developers want. NPM certainly had a bunch of "dumpster fires" for years IMO (lock files mess, signed code mess, etc.) but I feel most of those pain points have largely been addressed.
I downloaded Deno and tried it out, but at this point I'm just left thinking it doesn't really add anything for me that I need.
This is puzzling to me because I had the opposite reaction: among other things, Deno solves an incredibly important problem with Node, which is the complicated configuration used with most projects. Deno can perform, out of the box, many of the things you'd need to configure Webpack + Typescript to do:
SUBCOMMANDS:
bundle Bundle module and dependencies into single file
cache Cache the dependencies
completions Generate shell completions
doc Show documentation for a module
eval Eval script
fmt Format source files
help Prints this message or the help of the given subcommand(s)
info Show info about cache or info related to source file
install Install script as an executable
repl Read Eval Print Loop
run Run a program given a filename or url to the module
test Run tests
types Print runtime TypeScript declarations
upgrade Upgrade deno executable to given version
What would it take to get Node to do all of that? Which documentation tool would you choose, and how would you configure it? Testing? Bundling? Formatting?
If anyone remembers, this is similar to the “Turbo Gears” vs “Django” of Python world. Turbo Gears allowed me to choose the best of each component - but pretty soon one ends up having to upgrade or migrate to the new-best-sub-component on a weeekly/monthly basis. django helped avoided a lot of headache by defaulting a decent, but not necessarily the best tool, and sort of “won” in the end.
For some reason, we continue to replay this fight in each and every language and environment.
Totally agree with all that, but I also think it's one of those things that most devs hit the pain point for once, and then have a standard template project they use for everything going forward. I.e. I have all my webpack/tsc/eslint/prettier/jest boilerplate set up once, so now it's not really an issue for me.
I also think this is a problem area where the Romejs project is taking a better approach: simplify and fix the toolchain, instead of replacing the entire runtime.
Static compilation of JS into a binary is also being worked on (albeit slowly) with `deno compile`[0]. This is the feature I'm most looking forward to personally, goodbye JS slowness.
When node appeared, it was a 'huge thing' because you could run JS consistently on the server-side, with some kind of packaging scheme.
Most of the things you listed aren't going to be useful to most, even when they are, they are small things that can be managed otherwise. Though admittedly, everyone will runt into at least one of those issues.
For a large, complex deployment, there's no obvious reason at all to shift to Deno.
We'll have to wait and see how it works out for those who want to try it for fun.
I am actually really interested to see if something like Deno can take over in programming education.[1]
Deno's extremely simple import semantics and built-in tooling could make it a great environment for a learner. They won't have to be exposed to package management, they can just click a URL in their source code and see the exact source code they just imported.
All the stuff that professional developers can do and might want to do for themselves (setting up testing frameworks, pinning transitive dependency versions) is kind of out of scope for educational use. Unless that education is specifically targeted at "how to do modern JS development within this specific ecosystem".
The ease of bringing TypeScript into your Deno programs may make it easier to start "graduating" to static typing as part of the curriculum, without being like "okay, that was Python! Next up: Java!"
[1]: Say what you want about JavaScript, I don't see that modern JS is significantly worse than Python for learning to program (having watched a couple of students go through Python courses). All languages have their warts.
I'm not seeing enough in Deno that would tempt me to drop compatibility with the Node ecosystem. What I really want is actual Node.js with native TypeScript support.
The big deal here is security by default as enforced by the runtime (deno) itself - there is afaik none other doing anything remotely as cool anywhere. It in effect makes it super safe to run code since you have to explicitly allow the various levels of system access.
Also makes the system fundamentally unattractive to malware authors whereas installing modules via node.js is like leaving your front door open and taking a chartered holiday while hoping for the best.
Most folks running Node.js instances have control over all of the software they are running and 'security' in this sense just isn't a huge concern. Obviously, more security is alwasy better all things being equal, but it's not the big issue with Node.js.
It seems that Deno is probably a nicer, overall version of Node, and if we were 10 years ago, undoubtedly, we would chose Deno. But we're not, we have massive installed bases and operating capabilities, so the choice is less obvious.
Few things comes to my mind if you are moving from NodeJS to Deno:
1. Deno lacks the library eco system which is required to build a production level app today. I am not saying it cant be done. Just think of the different third party service integration modern application has to do, their maintainance and testing by individual vendors or open source contributors ! Blogs mentions few DB driver libraries, i highly doubt they are as mature.
2. Deno's security model overly hyped at least i see it this way. In last few version of NodeJS, many security flaws have been addressed, see their changelog if you dont believe me. But most importantly, security flaws with native JS is handled by V8 which is common to both NodeJS and Deno. On top of that, most of the libraries and frameworks in NodeJS during their various releases sorted out many security issues in their code. If someone is still doubtful they can use eslint-plugins for sanity and security checks in their JS files. Adopting Typescript also helps if you cant live without types.
3. Learning curve to adopt new SDK for Socket API, File API, System call API etc. I don't think NodeJS falls short significantly anywhere, in fact it provides more and those APIs have been relatively more battle tested over the years.
4. Irrespective of using NodeJS or Deno, following a BDD/TDD practices to ensure sound test coverage of your business use logic still remain the most promising tool to make, break and refactor your codebase.
Solely addressing #1 here, and this may come off harsh, but I think it's ridiculous to expect Deno to match the library ecosystem of Node on day 1. That's just literally impossible, but whenever a new language or runtime is released, it manages to become the most prominent question/concern.
It also is something of a moot point anyways, because people pushing something into production already are probably not using something so new. Early adopters don't care about how mature the ecosystem is; part of the appeal of being an early adopter is helping to build that ecosystem...
There's no way it's going to match everything, but regarding number 1 - it does look like you can drop in some node modules. A small example, but one that surprised me - React works. So you can do React with SSR with nothing else, eg. this demo is a pretty refreshing one to see how few moving pieces there are. https://github.com/brianleroux/arc-example-deno-ssr . It's just imported as `import { React, ReactDOM } from 'https://unpkg.com/es-react'`
By no means i am demotivating anyone. I have just enumerated the minimum possible evaluation criteria and current state of development. This is what i often do at my workplace as an Architect.
If someone is eager to try out new possibilities in Deno and their application use cases intersect well with what Deno has to offer, then by all means it's a good decision.
Regarding point 3, Deno's APIs use language features that were unavailable when node was written, including promises and async iterators. That is a big improvement IMO.
Thanks for doing this. I have a few questions regarding packages/dependencies, and TypeScript in general.
I tried installing Deno, and I tried including a package, and immediately the TypeScript typechecking in my IDE (VSCode) failed, of course. The IDE doesn't know what to do with a URL as a dependency. Is this something Deno will be able to handle?
The next question is that TypeScript packages I have written in the past use `baseUrl` and `paths` in their own configs to allow for absolute import paths. When I look at third-party Deno repositories, I didn't see any that were building out to JS/declaration files, and were instead just meant to be included as the original TypeScript source code. Won't this break things like absolute import paths and other behaviors of the dependency's own tsconfig file, or does this work fine with Deno/TS?
Using JavaScript outside a browser by running the V8 JavaScript browser engine on the server is a bit of a gimmick, but enough people can't bother to be a polyglot, and it's not that crazy.
But, once you are writing code in TS, then transpiling that to JS, then running that in V8 on a server, you have taken a big step into the Rube Goldberg dimension.
even better if deno bases their web renderer on servo since the deno runtime is rust and servo is rust. Would be great for getting some diversity back in the browser stack.
What Node is missing due to it's design is parallel (not just async-on-a-single-thread) processing using either green or OS threads without the overhead of serialization to web-workers or a cluster. Last time I checked, Deno didn't have a story there.
My brief skimming of its site indicates that its security model is based around the ability to disable, say, network access for whole Deno programs. However, does it allow starting up with network access, allowing a subset of the program to handle it, and then dropping those rights for the rest of the program, _especially_ subdependencies?
I can't see any mention of a more fine-grained approach: https://deno.land/manual/getting_started/permissions
A modern Node.js web service will have hundreds, if not thousands, of indirect dependencies. Some network access will be required for at least the Express routing, or an equivalent.
For a Deno equivalent, this would amount to enabling network access for all hundreds of those subdependencies, not reproducing the isolation in capability-based security such as WebAssembly nanoprocesses.
Have I missed something here? That doesn't seem like much of an improvement over Node.js except for very small and contained programs. Yes, Deno's dropping of centralised package repositories and package.json might alleviate this problem _somewhat_, but the same fundamental issue seems to remain.
While the grant is a blanket grant to a program and all dependencies, typically, a well behaved program will seek a limited scope of permissions. Like "https://my-program.com", "https://preferred-analytics.com" etc.
This prevents dependencies from using call back locations that are outside the permitted list, preventing much of the nefarious activity they can dream up.
If a dependency needs access to specific resources, it can advertise this fact and the parent module can in turn request this from the user.
Importantly, the user is explicitly aware of these & controls it in an absolute sense, at run time.
I mean, I guess I see value there for the use case of "I want to download a script to run locally on my machine" type of thing, but for the most common use of Node, i.e. I'm running a server process, does this really even matter?
https://github.com/denoland/deno/issues/2318
What about keeping the network allowed in the layer handling, say, inbound HTTP connections, but blocking it in the data access layer or purely computational component?
From what I can see, this doesn't work with global boolean flags in the runtime, instead requiring isolated tasks with whitelisted capabilities passed in, some form of "immutable, set-once, dynamically-scoped capability flags", or something like that.
The problem with the global boolean flag approach is that if any part of a service needs it constantly, the entire program gets it, even obscure subdependencies for generating colour pickers.
Don't get me wrong, it's an incremental improvement over's Node.js blase approach. It's also quite niche to see languages support this feature. E was one of them. There was another newer Python-like language with this too, starting with an `M`, but its name escapes me.
I'd recommend Deno's developers look at E a bit more before committing too much to the platform boolean flag approach. Or I've misunderstood their approach and it actually does more than I'm giving it credit for.
What would be really useful is if only sections of code can be delineated as requiring certain permissions. This way, it's much easier to see what parts of the code do what and also to make sure that users only get prompted for such permissions when the code actually runs.
I downloaded Deno and tried it out, but at this point I'm just left thinking it doesn't really add anything for me that I need.
For some reason, we continue to replay this fight in each and every language and environment.
I also think this is a problem area where the Romejs project is taking a better approach: simplify and fix the toolchain, instead of replacing the entire runtime.
[0] https://github.com/denoland/deno/issues/986
When node appeared, it was a 'huge thing' because you could run JS consistently on the server-side, with some kind of packaging scheme.
Most of the things you listed aren't going to be useful to most, even when they are, they are small things that can be managed otherwise. Though admittedly, everyone will runt into at least one of those issues.
For a large, complex deployment, there's no obvious reason at all to shift to Deno.
We'll have to wait and see how it works out for those who want to try it for fun.
Dead Comment
Deno's extremely simple import semantics and built-in tooling could make it a great environment for a learner. They won't have to be exposed to package management, they can just click a URL in their source code and see the exact source code they just imported.
All the stuff that professional developers can do and might want to do for themselves (setting up testing frameworks, pinning transitive dependency versions) is kind of out of scope for educational use. Unless that education is specifically targeted at "how to do modern JS development within this specific ecosystem".
The ease of bringing TypeScript into your Deno programs may make it easier to start "graduating" to static typing as part of the curriculum, without being like "okay, that was Python! Next up: Java!"
[1]: Say what you want about JavaScript, I don't see that modern JS is significantly worse than Python for learning to program (having watched a couple of students go through Python courses). All languages have their warts.
Also makes the system fundamentally unattractive to malware authors whereas installing modules via node.js is like leaving your front door open and taking a chartered holiday while hoping for the best.
Any operating system with "capabilities", "namespaces", "privileges", etc.
That includes Linux, Windows and many others.
It seems that Deno is probably a nicer, overall version of Node, and if we were 10 years ago, undoubtedly, we would chose Deno. But we're not, we have massive installed bases and operating capabilities, so the choice is less obvious.
For most systems, the raw performance of the JS just is not a bottleneck.
1. Deno lacks the library eco system which is required to build a production level app today. I am not saying it cant be done. Just think of the different third party service integration modern application has to do, their maintainance and testing by individual vendors or open source contributors ! Blogs mentions few DB driver libraries, i highly doubt they are as mature.
2. Deno's security model overly hyped at least i see it this way. In last few version of NodeJS, many security flaws have been addressed, see their changelog if you dont believe me. But most importantly, security flaws with native JS is handled by V8 which is common to both NodeJS and Deno. On top of that, most of the libraries and frameworks in NodeJS during their various releases sorted out many security issues in their code. If someone is still doubtful they can use eslint-plugins for sanity and security checks in their JS files. Adopting Typescript also helps if you cant live without types.
3. Learning curve to adopt new SDK for Socket API, File API, System call API etc. I don't think NodeJS falls short significantly anywhere, in fact it provides more and those APIs have been relatively more battle tested over the years.
4. Irrespective of using NodeJS or Deno, following a BDD/TDD practices to ensure sound test coverage of your business use logic still remain the most promising tool to make, break and refactor your codebase.
It also is something of a moot point anyways, because people pushing something into production already are probably not using something so new. Early adopters don't care about how mature the ecosystem is; part of the appeal of being an early adopter is helping to build that ecosystem...
If someone is eager to try out new possibilities in Deno and their application use cases intersect well with what Deno has to offer, then by all means it's a good decision.
https://nodejs.org/dist/latest-v8.x/docs/api/util.html#util_...
It was introduced in NodeJS 8.x release. The latest LTS version is 12.x
I tried installing Deno, and I tried including a package, and immediately the TypeScript typechecking in my IDE (VSCode) failed, of course. The IDE doesn't know what to do with a URL as a dependency. Is this something Deno will be able to handle?
The next question is that TypeScript packages I have written in the past use `baseUrl` and `paths` in their own configs to allow for absolute import paths. When I look at third-party Deno repositories, I didn't see any that were building out to JS/declaration files, and were instead just meant to be included as the original TypeScript source code. Won't this break things like absolute import paths and other behaviors of the dependency's own tsconfig file, or does this work fine with Deno/TS?
* https://marketplace.visualstudio.com/items?itemName=axetroy....
Looks like there's a plug-in. Can't research much now, but I hope there's something like that for emacs tide.
https://news.ycombinator.com/item?id=23172483
https://news.ycombinator.com/item?id=23093737
https://news.ycombinator.com/item?id=22102656
https://news.ycombinator.com/item?id=20373430
https://news.ycombinator.com/item?id=17183241
Let me know if I've missed any.
But, once you are writing code in TS, then transpiling that to JS, then running that in V8 on a server, you have taken a big step into the Rube Goldberg dimension.