Ryan Dahl, the creator of Node.js, has spent the past year and a half working on the
Deno project. This is a new JavaScript runtime that should fix the problems inherent in Node.js.
Do not misunderstand me. The Node.js platform is a great server environment for executing JavaScript. It owes its popularity mainly to a huge ecosystem, and, in fact, support for JavaScript. However, Ryan Dahl admits that he should have paid more attention to something related to Node.js. This, in particular, is about security, modules and dependency management.
One can say in his defense that he could not know how popular the Node.js platform would become in a relatively short period of time. In addition, in 2009, JavaScript still looked like a limited and strange language, which was ridiculed by all and sundry. It should also be noted that in those days many of the features of JavaScript, the usual in our day, did not exist.
What is Deno and what are the main features of this platform?
Deno is a TypeScript safe runtime environment built on the basis of the V8 JS engine developed by Google. Deno Platform is built using the following tools:
')
- Rust (the Deno kernel is written in Rust, and the Node kernel in C ++).
- Tokio (an event loop written in Rust).
- TypeScript (Deno, without additional settings, supports both JavaScript and TypeScript).
- V8 (JS engine from Google, used in Chrome browser, in Node.js and in other projects).
Let's talk about what features the Deno platform offers us.
Security (Permissions)
Among the most important features of Deno, to which special attention is paid, is security.
Unlike Node, Deno, by default, runs the code in the sandbox. This means that the runtime does not have access to the following entities and capabilities:
- File system.
- Network.
- Execution of other scripts.
- Environment variables
Take a look at how the Deno permissions system works. Consider the following script:
(async () => { const encoder = new TextEncoder(); const data = encoder.encode('Hello world\n'); await Deno.writeFile('hello.txt', data); await Deno.writeFile('hello2.txt', data); })();
This script creates a pair of text files -
hello.txt
and
hello2.txt
.
Hello world
placed in these files. The code is executed in the sandbox. Therefore, it does not have access to the file system.
Also, notice that here we are using the
Deno
namespace, rather than referring to something like the
fs
module, as we would have done in Node.
Deno
namespace provides the developer with many basic support functions. But we, using the namespace, lose the compatibility of the code with the browser. We will discuss this below.
This script can be run with the following command:
deno run write-hello.ts
After that we will see a notification with the following content:
Deno requests write access to "/Users/user/folder/hello.txt". Grant? [a/y/n/d (a = allow always, y = allow once, n = deny once, d = deny always)]
In fact, we may well see it twice during the execution of each of the calls. Of course, if we answer the question of the system by selecting the option
allow always
, the second time this notification will not be given to us.
If we choose one of the
deny
options, a
PermissionDenied
error will be issued. The script process will then be completed, since there is no code for handling errors.
The script can be run like this:
deno run --allow-write write-hello.ts
We will not see notifications, both files will be created.
In addition to the
--allow-write
flag, which affects the work with the file system, other flags can be used when running scripts. These are
--allow-net
,
--allow-env
and -
--allow-run
. They, respectively, provide the script with access to the network, to the environment, and to the launch of subprocesses.
Modules
Deno, like browsers, loads modules by URL. Many are confused at first by what they see in the server code of an import command from a URL. But this, in fact, makes sense. Wait a bit - and you will understand it yourself.
import { assertEquals } from "https://deno.land/std/testing/asserts.ts";
Here you may have a question about what is so special about importing packages by URL? The answer to this question is simple: thanks to the use of URLs, Deno packages can be distributed without using a centralized registry like npm. Npm has had a
lot of problems lately.
Organizing the import of code through a URL allows package creators to host their code wherever they see fit. This is decentralization in all its glory. No more
package.json
and
node_modules
.
When we run the application, Deno loads all imported modules and caches them. After they are cached, Deno will not reload them unless we explicitly request them to
--reload
using the
--reload
flag.
Regarding this system of working with modules, you can ask a few important questions.
â–ŤWhat if the resource where the module code is located will be unavailable?
Module code is not stored in a centralized registry. Some web resource on which this code is located may be unavailable for a variety of reasons. In the development process, or, even worse, bringing the project into production, it is risky to hope that the hosting of the module will always be available.
As already mentioned, Deno caches loaded modules. Since the cache is stored on a local disk, the creator of Deno recommends processing it with the means of a version control system (that is, git) and including it in the project repository. With this approach, even when the resource on which the code is stored is unavailable, all project developers will retain access to the loaded versions of the modules.
Deno stores the cache in the folder specified by the
$DENO_DIR
environment variable. If we do not configure this variable, Deno will store the cache in the standard system directory for caches. The variable
$DENO_DIR
can be set so that it points to a folder in our local repository. This folder can be processed using your version control system.
â–ŤIs it necessary to constantly import modules by URL?
Regular entry of long URLs can quickly get bored. Fortunately, Deno gives us two ways to make this task easier.
The first way is to use the ability to re-export the imported module from a local file. For example, it might look like this:
export { test, assertEquals } from "https://deno.land/std/testing/mod.ts";
Suppose that the file in which the above command is located is called
local-test-utils.ts
. Now, if we again need the
test
or
assertEqual
, we can import them like this:
import { test, assertEquals } from './local-test-utils.ts';
As a result, it turns out that it does not matter whether the module was loaded by URL or not.
The second possibility is to create an import map, designed as a JSON file:
{ "imports": { "http/": "https://deno.land/std/http/" } }
When using such a file, the import command may look like this:
import { serve } from "http/server.ts";
In order for this scheme to work, you need to inform the system about the use of an
--importmap
map in a project, using the
--importmap
flag when starting the script:
deno run --importmap=import_map.json hello_server.ts
â–ŤHow is module versioning managed?
The version management of packages is the responsibility of their developer. From the client’s point of view, choosing the right version of the package looks like adding it to the URL:
https://unpkg.com/liltest@0.0.5/dist/liltest.js
.
Browser Compatibility
The Deno platform is committed to the compatibility of its code with browsers. From a technical point of view, when we use ES modules, we are not obliged to use some kind of assembly tools, like a webpack, which provide the ability to run the application in a browser.
However, tools like Babel convert modern JS code to code that complies with the ES5 standard. As a result, this code can be run even in non-newer browsers that do not support modern JavaScript features. But this approach also has a minus, which is that web project bundles grow because a lot of auxiliary code falls into them.
Strictly speaking, we make decisions about the goals of our projects. We choose the appropriate tools.
TypeScript support
Deno makes it easy to use TypeScript, eliminating the need for a developer to customize anything to run TS code. But programs for Deno can easily be written in JavaScript.
Results
Deno, a new runtime for TypeScript and JavaScript, is an interesting project that has been showing steady development for some time. However, before he can be considered ready for production, he still has a long way to go.
The decentralized approach to working with modules, implemented in Deno, aims to free the JavaScript ecosystem from a centralized package repository, which is npm today.
Ryan Dahl says he expects to release Deno 1.0 at the end of the summer. If you are interested in the future of this project - pay attention to its
repository .
Dear readers! What do you think about Deno?
