Deno

Why Deno ?

Deno is a JavaScript & TypeScript runtime built on V8 -- the same JavaScript engine used by the Google Chrome browser. The origins of Deno are rooted in Node JS, which is another JavaScript runtime that's also built on the V8 JavaScript engine.

If the need to build something on top of a perfectly good JavaScript engine used by a mass-market browser like Google Chrome confuses you, let's break down this need:

Then the same person who pioneered Node JS armed with the hindsight of what would make a better Node JS[1] set out to create Deno. Therefore, Deno is an improved amalgamation of JavaScript features and concepts, built on top of the many lessons learned around Node JS, which in itself is at the center of modern JavaScript. That said, if you landed here without any prior knowledge about what led up to Deno, I'd recommend you first read the Node JS chapter and TypeScript chapter.

Deno - Installation and versioning

Deno is still relatively new, so there's only one major version 1.x vs. Node JS which has seventeen major versions. Therefore you can focus on the latest Deno version or Deno CLI (Command Line Interface).

Deno is written in Rust, which means you can build and install it from source on any operating system (OS) with Rust's package manager cargo. In addition to installing it from source, Deno is also available through various OS installers/package managers. Table 10-1 shows Deno installation instructions by operating system and installer/package manager:

Table 10-1. Deno installation instructions by installer/package manager
Operating SystemInstaller/package managerVersionCommand
All OS'sFrom source (Cargo/Rust) Most recentcargo install deno --locked
Specific versioncargo install --version 1.12.2 deno --locked
Linux & MacHomebrew Most recentbrew install deno
Specific versionbrew install deno@1.12.2
Linux & MacShell Most recentcurl -fsSL https://deno.land/x/install/install.sh | sh
Specific versioncurl -fsSL https://deno.land/x/install/install.sh | sh -s v1.12.2
LinuxSnap Most recentsudo snap install deno
Specific versionsudo snap install deno --channel=1.12.2/stable
WindowsPowerShell Most recentiwr https://deno.land/x/install/install.ps1 -useb | iex
Specific version$v="1.12.2"; iwr https://deno.land/x/install/install.ps1 -useb | iex
WindowsChocolatey Most recentchoco install deno
Specific versionchoco install deno --version 1.12.2 -my
WindowsScoop Most recentscoop install deno
Specific versionscoop install deno@1.12.2

As you can see in table 10-1, there are multiple options to install Deno across operating systems. Inclusively, there are less popular installers/package managers not shown in table 10-1, which include: Macports for Mac OS and Pacman for Linux OS.

Once you successfully install Deno, it provides a deno executable that's either administered by a package manager or installed on a user's home directory under the .deno folder inside the bin sub-directory (e.g. for a user called admin, the Deno executable will be in /home/admin/.deno/bin/).

The deno executable is tied to three versions:

If you run the deno executable with the --version flag you'll see the details of these versions, as shown in listing 10.1.

Listing 10-1. Versions associated with Deno, using deno --version
[user@laptop]$ deno --version
deno 1.16.2 (release, x86_64-unknown-linux-gnu)
v8 9.7.106.5
typescript 4.4.2

Listing 10-1 shows the deno executable is associated with the Deno CLI version 1.16.2, the V8 version 9.7.106.5 -- which corresponds to the same V8 engine used by Google Chrome Browser version 97 -- and TypeScript version 4.4.2

Note Deno also uses a versioning scheme for its standard modules, currently at a sub-1.0 version (e.g. 0.109.0). Loosely speaking, this shouldn't matter since only the Deno CLI version is the one that matters for end users. Every Deno CLI version is always pegged and compatible against a given Deno standard module version as described in this mapping list.

The deno command

The deno command is the main and only executable included with Deno.

If you have prior experience with Node JS, having only one executable in Deno might surprise you, since Node JS installations are equipped with three executables: node, npm and npx. You can use npm with Deno if you so please, although you probably won't need it due to the way Deno works with packages, as I'll explian shortly. Just as you can also rely on an equivalent npx for Deno called dpx[2]. So in this sense, Deno uses a more compact approach to supporting features which are all available through its single deno command.

The variety of features in the deno command are supported through three different approaches:

deno environment variables

Deno environment variables are designed to configure behaviors that won't change every time Deno is run. This makes Deno environment variables well suited for things like network access configurations, network credentials, as well as general purpose locations and formatting.

Over half of Deno's environment variables are associated with network related tasks, while the rest are for miscellaneous tasks. Table 10-2 illustrates the deno command's environment variables.

Table 10-2. deno enviornment variables
PurposeEnvironment variableDescription
Network security/accessDENO_AUTH_TOKENSA list of authentication tokens separated by ; to fetch modules hosted in private repositories (e.g. Github). Tokens can be in two formats: a bearer token in the form {token}@{hostname[:port]} or HTTP Basic auth credentials in form {username}:{password}@{hostname[:port]}. If Deno attempts to fetch a module with a matching hostname in DENO_AUTH_TOKENS, Deno adds the necessary authentication credentials via the HTTP Authorization header with a value of Bearer: {token} for bearer tokens or a value of Basic {base64_encoded_username_password} for HTTP Basic auth credentials.
DENO_CERTLocation of .pem file to use as a certificate authority.
DENO_TLS_CA_STORECertificate store(s) to use for secure connections: mozilla, system or both as a CSV (e.g.mozilla, system). If DENO_TLS_CA_STORE is unspecified, the default value is mozilla. If DENO_TLS_CA_STORE is given an empty value, no trust is given to secure connections unless a certificate is specified via DENO_CERT, the --cert flag or an explicit certificate is provided per secure connection.
HTTP_PROXYThe proxy address to use when Deno attempts to perform HTTP requests.
HTTPS_PROXYThe proxy address to use when Deno attempts to perform HTTPS (secure) requests.
NO_PROXYA CSV list of hostnames or addresses to bypass proxy configurations defined in either HTTP_PROXY or HTTPS_PROXY.
Directory definitionsDENO_DIRLocation to store Deno's cached information, which includes: cached remote modules, cached transpiled modules, language server cache information and persisted data from local storage. If DENO_DIR is unspecified, the default directory is the OS default cache location.
DENO_INSTALL_ROOTLocation to store Deno's installed scripts when using deno install. If DENO_INSTALL_ROOT is unspecified, the default directory is a user's .deno/bin directory (e.g. for a user called admin, Deno installs scripts in /home/admin/.deno/bin/).
DENO_WEBGPU_TRACELocation to store WebGPU traces.
FormattingNO_COLORConfigure Deno to not send ASCII color codes when writing to standard output and standard error. If NO_COLOR is unspecified, the default is for Deno to use ASCII color codes when writing to standard output and standard error.

deno flags

Deno flags are designed to configure behaviors that change every time Deno is run. In the past section, in listing 10-1 you already learned how the deno command supports the --version flag to get the Deno CLI version and its associated JavaScript V8 engine version & TypeScript version.

Deno flags can be used with the main deno command, as well as deno subcommands. There are global flags applicable to both the main deno command and deno subcommands, as well as flags that apply specifically to each one. For example, the --version flag available in the main deno command -- shown in listing 10-1 to output Deno version information -- only applies to the main deno command and a couple of other deno subcommands.

The following global flags can be used with both the main deno command, as well as all deno subcommands.

deno subcommands

The deno command supports over a dozen subcommands. The purpose of Deno subcommands is to simplify executing tasks with the deno executable by means of a keyword vs. offering multiple executables for different Deno tasks. Upcoming sections describe each of these subcommands in greater detail and the following list presents their high level purpose by group.

Upgrading Deno: deno upgrade

Looking back at table 10-1, you can see it's possible to install specific Deno versions using flags for each installer/package manager. However, it's worth pointing out that once installed, the deno executable itself is also equipped with the ability to overwrite itself with specific Deno versions through the deno upgrade subcommand and its --version flag. This process is illustrated in listing 10-2.

Listing 10-2. Deno version changes with deno upgrade and its --version flag
[user@laptop]$ deno upgrade --version 1.12.2
Checking https://github.com/denoland/deno/releases/download/v1.12.2/deno-x86_64-unknown-linux-gnu.zip
31.1 MiB / 31.1 MiB (100.0%)
Deno is upgrading to version 1.12.2
Archive:  /tmp/.tmpD4pEq4/deno.zip
  inflating: deno                    
Upgraded successfully

[user@laptop]$ deno --version
deno 1.12.2 (release, x86_64-unknown-linux-gnu)
v8 9.2.230.14
typescript 4.3.5

[user@laptop]$ deno upgrade
Looking up latest version
Found latest version 1.16.3
Checking https://github.com/denoland/deno/releases/download/v1.16.3/deno-x86_64-unknown-linux-gnu.zip
31.5 MiB / 31.5 MiB (100.0%)
Deno is upgrading to version 1.16.3
Archive:  /tmp/.tmpfLOY9d/deno.zip
  inflating: deno                    
Upgraded successfully

[user@laptop]$ deno --version
deno 1.16.3 (release, x86_64-unknown-linux-gnu)
v8 9.7.106.5
typescript 4.4.2

The first command in listing 10-2 deno upgrade --version 1.12.2 changes the installed deno version to 1.12.2. You can see this command download's the specified version from Deno's github repository and performs the installation/overwrite operation. Next, you can see the same deno --version command from listing 10-1 is used to confirm the version change, in this case, you can confirm all versions associated with the deno executable changed: Deno CLI to 1.12.2; V8 to 9.2.230.14; and TypeScript to 4.3.5.

The third command in listing 10-2 deno upgrade lacks the --version flag and as such upgrades Deno to the latest available version. In this case, you can see Deno is upgraded to version 1.16.3. The fourth command in listing 10-2 is deno --version that confirms all three versions associated with deno executable were updated: Deno CLI to 1.16.3; V8 to 9.7.106.5; and TypeScript to 4.4.2.

The --version flag used in the first statement in listing 10-2 belongs to the deno upgrade subcommand and shouldn't be confused with the --version flag available in the deno command, since the former is used to specify a version number to upgrade to and the latter is used to output Deno's installed version.

In addition to the --version flag and the Deno global flags, the deno upgrade subcommand also supports the following flags:

A TypeScript & JavaScript REPL: deno repl

REPLs are a common tool in many programming languages to test out language statements without the need to perform complex setups. The deno REPL mode provides access to a TypeScript & JavaScript environment in which you can interactively evaluate TypeScript & JavaScript statements.

Go ahead and execute deno without any arguments to enter the REPL mode as illustrated in listing 8-4, or alternatively, you can also use the more explicit command deno repl to enter the same REPL mode.

Listing 10-3. deno REPL mode with TypeScript and JavaScript
[user@laptop]$ deno
Deno 1.16.3
exit using ctrl+d or close()

// TypeScript statements
var letter: string = 'b';
let digit: number = 2;
const vowels: string[] = ['a', 'e', 'i', 'o', 'u'];
function worldMessage(message: string) { 
  console.log(`${message} World!`)
}

// JavaScript statements
var vowel = 'a';
let prime = 1;


// JavaScript Array method on TypeScript reference
vowels.indexOf(vowel);


// Call to method with TypeScript string argument
worldMessage("Hello");


// However, Deno REPL still doesn't do type checking
letter = 3;
worldMessage(digit);

The first four statements in listing 10-3 make use of TypeScript's static data type syntax (e.g. : string, : digit) to indicate the types of acceptable values assigned to references. In this Deno REPL mode, behind the scenes Deno transpiles TypeScript statements into JavaScript to execute them. The next two statements vowel and prime are plain JavaScript statements, illustrating how Deno's REPL mode is capable of simultaneously running both TypeScript and JavaScript. Next, a call is made on the vowels reference -- originally declared as a TypeScript string array -- with JavaScript's Array indexOf() method, in addition, a call is also made on the worldMessage() function which uses a TypeScript string argument.

The last two statements in listing 10-3 illustrate one of the TypeScript limitations in Deno's REPL mode, which is a lack of type checking[3]. The letter = 3 assignment should throw an error on account of the initial declaration var letter: string that pegs the reference to string values, similarly, the call worldMessage(digit) should also throw an error on account of the digit value being a number, when the method argument message: string requires string values.

Note The lack of TypeScript type checking behavior in Deno only applies to its REPL mode. Deno executes TypeScript as expected outside REPL mode, as shown in upcoming sections.
Tip There are more mature TypeScript REPLs than Deno, such as ts-node available in Node JS. See How to run TypeScript ? for additional details.
  1. https://www.youtube.com/watch?v=M3BM9TB-8yA    

  2. https://deno.land/x/dpx    

  3. https://github.com/denoland/deno/issues/11078