I'll be more than happy to answer your questions about Deno and its development.
I'll be more than happy to answer your questions about Deno and its development.
The Deno docs here almost seem to purposefully avoid answering this question: https://deno.land/manual@v1.6.0/examples/import_export
For packages that use native Node APIs there's a Node compatibility layer being developed as part of the standard library: https://deno.land/std@0.80.0/node. It's still lacking a lot of modules and doesn't provide seamless experience, but with every release it's getting better.
You can achieve the same thing with Deno! By default Deno downloads all dependencies into a central cache directory, but by providing DENO_DIR env variable with a path you can tell Deno to change that cache dir. And these files are cached indefinitely; Deno will not try to fetch them again on next run (unless you opt into it with --reload flag).
I want to have a central repository of all the package versions with enforced monotonically increasing version numbers and a public, explicit chain of trust. Otherwise it's basically curl | sh with all its associated problems https://docs.monadical.com/s/against-curl-sh
Using URLs means there are no rules enforced, the code hosted at that URL can change out from under you without any warning. A new developer checking out our repo could fetch totally different packages than everyone else on the team and not have any warning about it being different, or any recourse if they wanted to fetch a previous version.
The ecosystem is still in evolution but I expect that it stabilize around a few generic registries for smaller libs, and larger libs hosting their code themselves in the long run. The point is; while URLs _can_ be very loosy goosy ways to address code, they can also be made very strict - it will depend on the actual server behind it.
As a side note, npm is already pretty poor at providing those guarantees anyway, I find it interesting that it's usually assumed to be a safe way to install dependencies.
You lose automatic updating, but I'm not sure I want that anyhow. A script that goes looking for new versions of 3rd party modules would be fairly trivial I think.
I'm getting on this boat after mongoose changed its type definitions and ruined a whole morning of work for me.
[1] https://kitsonkelly.com/posts/deno-is-a-browser-for-code/
The real appeal of Deno for our org is the stdlib, which as a side effect means we can depend on fewer packages. The wholesale removal of the package manager seems like an unwanted pain that will only keep us away from switching and gaining the stdlib benefits.
deno run --allow-write=~/.myapp https://myapp.io/install.ts
It works quite well as secure scripting runtime.
It's strange to me that Deno seems as if it could decide overnight to be a drop-in replacement, but there's deliberate friction designed into the system here to try and push people away from node_modules? The upshot of that choice is that I'm unlikely to switch to Deno until that's changed (and I suspect that's the case for many other companies as well).
I love the direction the node compatibility layer is going in though https://deno.land/std@0.80.0/node, now I just wish it supported normal import statements from node_modules (not just require()). I'm quite excited about Deno overall, just waiting for it to get to drop-in point.
The 1.0 announcement post the team mentioned:
> For some applications Deno may be a good choice today, for others not yet. It will depend on the requirements. We want to be transparent about these limitations to help people make informed decisions when considering to use Deno.
and:
> Over time, we expect Deno to be able to run more and more Node programs out-of-the-box.
I don't think they've ever claimed to be an immediate drop-in replacement.
https://www.npmjs.com/package/@import-maps/generate/v/0.1.0
This way you'd get both the benefits of web standards compliance with the generated explicit import maps, and backward compatibility and ease-of-migration for npm/yarn users.
How is using a URL different from using a NPM package? In both cases you can specify a module, a version, and need to trust some remote server that it is sending you the correct files.
> the code hosted at that URL can change out from under you without any warning
The same can and has happened with NPM. See left-pad.
Left pad was promptly fixed! That's an argument for a centralized package manager, not against. If it were hosted on some private server we'd all still be screwed.
How is that important? Most Deno packages are imported from GitHub (or deno.land). Neither NPM nor GitHub want to lose your code.
> Left pad was promptly fixed! That's an argument for a centralized package manager, not against.
This is not an argument for a central package manager, but an argument for a central package repository.
Deno is already a "central package manager". Similar to NPM in Node development, Deno is the default tool to download code in Deno development. Both with Node or Deno, you can download code in other ways, too. Nobody forces you to load code from URLs via import statements or NPM packages via npm install and commonjs require. (Also, when it comes to executing random code from the internet, Deno has a sandbox. Node doesn't.)
And yes, well maintained package repositories are great. Whether centrally or decentrally managed repos are better is up for debate, though.
In any case, if you want to use NPM packages in Deno, I'd recommend https://www.skypack.dev/. It's "NPM packages from a URL", so, as we have established earlier, it's just as much reliant on trust and potentially unstable as anything in life, but at least their left-pad is patched...
Import maps allow you to do that, see: https://deno.land/manual/linking_to_external_code/import_map...
Also, it seems as though ./node_modules/ being the default could be assumed automatically though, no?
"imports": {
"moment": "/node_modules/moment/src/moment.js",
"lodash": "/node_modules/lodash-es/lodash.js"
}
Considering it's the default in all other JS environments, wouldn't that save the hassle of the dev having to define this for their entire tree of JS dependencies? Then Deno would be a drop-in replacement and we could move our whole codebase over to it overnight (once the Node APIs are up to par).No, there is no magic node_modules directory in any other JS environment, other than Node. Deno aims to be compatible with web standards. Import and import maps are web standards, require and node_modules aren't.
> Deno would be a drop-in replacement and we could move our whole codebase over to it overnight
The reason that you cannot move your existing codebase to Deno tonight is essentially the poor web compat of the existing Node ecosystem.
I don't think you can blame the incumbent tool with complete market dominance for "poor compatibility"...
I really like the direction of the Node compatibility layer though https://deno.land/std@0.80.0/node, I suspect it will be enough to make Deno a drop in replacement soon. Now it just needs support for normal `import` statements from node_modules instead of just `require()`.
How dare Node not be compatible with the market dominating jQuery! Silly server-runtime not having a browser window object!
> Now it just needs support for normal `import` statements from node_modules
Deno will never ever do that (other than by using standardized import maps) since that's not normal (normal meaning standardized).
import $ from "jquery"
> Deno will never ever do thatWhy would Deno take such an antagonistic approach to supporting the most common setup that everyone uses with npm? Wouldn't it be trivial to just fall back to checking node_modules for named packages? I want to use Deno! This seems like it's deliberately making transitions difficult for anyone using npm.
The fact remains that the most popular JS env is the browser. It has APIs such as window which are not compatible with Node and Node has APIs which are not compatible with the browser like __dirname or require. That's why tools such as browserify and webpack exist to bridge the gap.
In Deno the gap is much closer. Obviously, the Deno namespace is not available in the browser (but there's a shim for most APIs, e.g. Deno.writeFile and readFile are implemented with a virtual FS) and some web APIs are not available in Deno (yet), but the compat story is much better.
This is no surprise since web compat is a core goal of Deno. Node compat is not.
> Wouldn't it be trivial to just fall back to checking node_modules for named packages?
No, the resolution algo is not trivial (nor performant). Also, it's not necessary: There is already a standard for how to import code in JS; it's import statements. Import statements do not allow named packages, e.g. import $ from "jquery" does not work in the browser. Except, again, import maps.
:'( That's a shame, it would make such a good node replacement with a great stdlib and Typescript support. I hope they reconsider in the future.
These (and other) disruptive breaking changes are about fixing mistakes that cannot be fixed (or at least, are hard to fix) in Node.
Maybe, in a few years, you'll say something like "Oh, I wish legacy Node would be more Deno compatible" because Deno will be the de-facto server-side JS scripting runtime. Equally, it's possible that Deno will fail, but that many good ideas will be incorporated into Node as breaking changes.
Node and Deno as well as their environments can grow further together or further apart. I think it's too early to tell which future is more likely.
For large projects like React, lodash, eslint whatever, I expect some of them will start hosting their libraries on their own networks, like it used to be when Javascript was only frontend and you would have a script tag importing jQuery directly from jQuery's CDN. The reason it worked was because jQuery was sidely known and trusted.
My understanding is these are loaded from URLs if they are not in the cache. If a domain changes hands, you could be served anything.
The truth is, even with a centralized repository, we're still importing user-code, made by humans that may not be well intentioned or simply not know that their code is vulnerable: proxying within your network and running periodic checks against the content of the local cache would be good practice, no where the code came from
1. https://github.com/denoland/deno/issues/1891
edit:
partial webcrypto/wasm option already available
Looks like Deno can run .ts files without first compiling to .js. What are the other benefits?
Deno is different than Node in several aspects; most notably:
- Deno supports only ES modules, there's no built-in support for CommonJS modules
- Deno's APIs are all promised based
- Deno does not use NPM, instead it can pull code from any URL, much like browsers do
- Deno has built-in permission system that by default runs your code in full sandbox allowing to opt-in into breaking out of sandbox (eg. to read a file from disk)
- As you've mention Deno can run .ts files without explicit build step
- Deno comes with a full toolchain in a single binary (formatter, linter, test runner, bundler, doc generator)
Promises are very complicated compared to first class functions. What makes JS/Node hard to grasp is that it's async. Async is an (often unnecessary) optimization, with tradeoffs.
Loading modules from URL's is a cool concept! ES modules helps here, but you could also have a package-list file that lists all dependencies of dependencies as well as download mirrors, or hashes with peer-to-peer distribution.
A permission system is nice, modules should not have system access by default.
Not everyone wants to use TypeScript. It will probably become obsolete once optional type annotations gets added to JavaScript.
An opinionated toolchain is nice, but should be optional IMHO.
I'm not sure what you mean by "bad practices like include files" so I can't comment on that.
I've found most Javascript developers prefer the await syntax with promises to using callbacks. It gives the code the appearance of being synchronous with the ability to do things more asynchronously if you need. I haven't encountered many who actively prefer the callback style. It gets unruly fairly quickly.
I can't see optional type annotations ever being added to Javascript. They would have to be checked at runtime which isn't something I'd imagine browser vendors wanting to implement.
The feeling that I get is that the standards committee is trying to bring Javascript to be the best dynamic language it can be and if people want more comprehensive guarantees then there are excellent tools like Typescript which give that option.
The fact there have to be multiple implementations of the standard in the various JS runtimes makes it a hard sell to evolve Javascript too far.
Its in Typescript 3.8, Node 14.8 and probably in your Babel setup. I probably wont get to use Node 14 in prod for a while but I get by with a `main` function that has everything in that gets called at the bottom.
That's not true any more, ES Modules have made it into the spec, so that's what Deno is using.
As for package-lists, the current convention in the community at the moment if you have a decently sized library is to have a `deps.ts` file where you re-export all of your dependency, making it an equivalent to package.json and helps with upgrading dependencies across a codebase.
TypeScript is already optional in Deno! it will run any .js file just fine, and you even skip the compilation part.
You don't have to use TS. Deno runs plain JS, too.
> [TypeScript] will probably become obsolete once optional type annotations gets added to JavaScript.
What makes you think that type annotations will be added to JS? I think it's far more likely that browsers and other runtimes will natively support TS as a separate language rather than JS evolving to become TS.
> An opinionated toolchain is nice, but should be optional IMHO.
It is optional. You don't have to run deno lint, deno fmt, deno test, etc. But at the same time, they are pretty good tools so you might want to try them.
It has already been tried with Dart. Dart was made because JS lacked a type system, preventing further optimisations. Support for Dart was added in Chrome.
Another popular JS transpiler is CoffeeScript, most of it's syntax is now in JavaScript.
Support for Dart in Chrome was added before Dart was popular (if you can even consider it popular at all). Since TypeScript is already popular now, I think if Chrome added support for stripping the types and running TS code as JS, most devs would welcome that.
I've tried to get Deno to work before in production, but it had so many compatibility issues last I tried it would take weeks or months to refactor things so it would work.
If you write a library, you need to support several export types for node packages. In your `package.json` you must include a `main` `module` and `exports` object and provide two compiled outputs, one commonjs and one es modules.
Then you need to worry about mutating import paths to include the file extension, which can cause trouble when you keep the commonjs and esmodule files in the same folder.
Also the esmodule loader in node doesn't have access to things like `__dirname`, so certain things can break.
not to mention node_modules...
It's like IE support but on the back end.
Then you step into the front end and it's another whole layer of chaos.
Give me opinionated compilers with minimal configuration and let me write code.
This is a hassle, but didn't used to be true for node - you could say the same as all the above for commonjs, wasn't it nice to have a single opinionated standard.
In the short term, deno avoids this by dropping backwards compat, great! But in the long term, I don't see how it doesn't end up in exactly the same place as soon as the next big change to JS modules comes out, or the next new build environment or wasm integration becomes bigger or...
Unless they have a fundamentally different strategy for the future (either 'we will never evolve' or 'we will evolve with ecosystem-wide breaking changes') they're going to end up in the same state as node today, eventually. I haven't seen any discussion of such a strategy at all. It's just a temporary reset - unlike node, they get to break backward compat and support the One True Format because they're new, that's all.
I completely agree with that! But on the other hand with plethora of tools available it can be quite overwhelming to configure all the tools, especially for new users.
> I've tried to get Deno to work before in production, but it had so many compatibility issues last I tried it would take weeks or months to refactor things so it would work.
Work on compatibility layer with Node is ongoing [1]. With every release there's some new API being compatible, but far from over.
Nobody forces you to use the deno dev tools. You can still run eslint, prettier and closurescript, if that's your sort of thing.
Personally, I prefer deno lint over eslint and deno fmt over prettier since they are much faster. I'm even using dprint (which is a standalone project for code formatting, https://dprint.dev/) in Node projects.
Similarly, before deno test, I created my own deno testing tool. Now I use deno test instead since it's just better - not because anyone's forcing me to use it.
The integrated dev tools are a convenience feature. I hope that's kinda obvious.
Last I remember is that every project/library has vastly different tsconfigs.