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:
- The V8 engine is capable of running plain JavaScript, like all the other JavaScript engines used by mass-market browsers.
- Because plain JavaScript was conceived to run on browsers, its core functionalities have always been limited. This gave way to Node JS, allowing the execution of JavaScript outside of browsers.
- Node JS brought with it new JavaScript features, like built-in JavaScript modules to perform more elaborate JavaScript tasks (e.g. read/write files, cryptographic tasks), as well as the JavaScript npm package manager to handle JavaScript package management, which is something JavaScript had lacked since its inception vs. other programming languages.
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 System | Installer/package manager | Version | Command |
---|---|---|---|
All OS's | From source (Cargo/Rust) | Most recent | cargo install deno --locked |
Specific version | cargo install --version 1.12.2 deno --locked | ||
Linux & Mac | Homebrew | Most recent | brew install deno |
Specific version | brew install deno@1.12.2 | ||
Linux & Mac | Shell | Most recent | curl -fsSL https://deno.land/x/install/install.sh | sh |
Specific version | curl -fsSL https://deno.land/x/install/install.sh | sh -s v1.12.2 | ||
Linux | Snap | Most recent | sudo snap install deno |
Specific version | sudo snap install deno --channel=1.12.2/stable | ||
Windows | PowerShell | Most recent | iwr 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 | ||
Windows | Chocolatey | Most recent | choco install deno |
Specific version | choco install deno --version 1.12.2 -my | ||
Windows | Scoop | Most recent | scoop install deno |
Specific version | scoop 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:
- The
deno
version itself (a.k.a CLI version). - The V8 version of the JavaScript engine included with Deno
- The TypeScript version supported by Deno.
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:
- Environment variables.- Are operating system (OS) level configurations to influence Deno's operation.
- Flags.- Are command line arguments specified with the
deno
command using either-
or--
to influence Deno's operation. - Subcommands.- Are command line arguments specified after the
deno
command to trigger specific Deno tasks, with each subcommand also supporting its own specific flags.
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
Purpose | Environment variable | Description |
---|---|---|
Network security/access | DENO_AUTH_TOKENS | A 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_CERT | Location of .pem file to use as a certificate authority. | |
DENO_TLS_CA_STORE | Certificate 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_PROXY | The proxy address to use when Deno attempts to perform HTTP requests. | |
HTTPS_PROXY | The proxy address to use when Deno attempts to perform HTTPS (secure) requests. | |
NO_PROXY | A CSV list of hostnames or addresses to bypass proxy configurations defined in either HTTP_PROXY or HTTPS_PROXY . | |
Directory definitions | DENO_DIR | Location 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_ROOT | Location 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_TRACE | Location to store WebGPU traces. | |
Formatting | NO_COLOR | Configure 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 --help
ordeno -h
.- Outputs the help menu for a givendeno
command/subcommand.deno --log-level [debug|info]
ordeno -L [debug|info]
.- Sets the log level for Deno, wheredebug
orinfo
are valid values. If not specified, the default Deno log level isinfo
.deno --quiet
ordeno -q
.- Limits Deno subcommand output to errors. If not specified, by default Deno subcommands print diagnostic messages not just errors.deno --unstable
.- Enables Deno unstable features and APIs. If not specified, by default Deno does not enable unstable features and APIs.
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.
- Deno build tasks:
deno bundle
.- Bundles modules and dependencies into a single file.deno compile
.- (Unstable) Compiles a script into a self contained executable.deno doc
.- Generates documentation for a module.deno fmt
.- Formats JavaScript, TypeScript, Markdown and JSON files.deno lint
.-Lints JavaScript/TypeScript files.
- Deno command line utilities:
deno completions
.- Outputs a bash script with auto-completions to make it easier to exploredeno
flags and subcommands from the command line.deno eval
.- Evaluates JavaScript/TypeScript from the command line.deno help
.- Outputs global Deno help options or those for a given Deno subcommand.deno repl
.-Starts Deno's TypeScript & JavaScript REPL (Read Eval Print Loop).deno types
.- Outputs runtime TypeScript declarations.
- Deno dependency tasks:
deno cache
.- Caches and compiles remote dependencies.deno info
.- Outputs dependencies and other information associated with a file (e.g. file path & type [JavaScript, TypeScript]).
- Deno run-time tasks:
deno install
.- Installs a script as an executable in Deno's root bin directory.deno uninstall
.- Uninstalls an executable script -- previously installed withdeno install
-- in Deno's root bin directory.deno lsp
.- Starts Deno's language server to allow code editors & IDE (Integrated Development Environments) to interact with Deno.deno run
.- Runs a JavaScript/TypeScript program, which by default is run in a sandbox environment without access to disk, network or the ability to spawn subprocesses.deno upgrade
.- Upgrades thedeno
executable to the latest version or a provided version.
- Deno testing tasks:
deno coverage
.- Generates coverage reports from a coverage profile.deno test
.- Runs tests associated with a Deno project.
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:
deno upgrade --canary
.- Upgrades Deno to the most recent canary build. A canary build represents the latest -- generally minimally tested -- release, therefore this flag upgrades Deno to the latest features. If not specified,deno upgrade
upgrades to the latest official minor release.deno upgrade --cert <file>
.- Points to a certificate to use for the Deno upgrade. A certificate can also be specified with theDENO_CERT
environment variable. If not specified,deno upgrade
uses built-in certificates configurable with theDENO_TLS_CA_STORE
. Seedeno
environment variables for additional details on these environment variables.deno upgrade --dry-run
.- Performs all upgrade checks, without overwriting thedeno
executable. If not specified,deno upgrade
overwrites the pre-existingdeno
executable.deno upgrade --force
ordeno upgrade -f
.- Forces thedeno
executable to upgrade even if its up to date. If not specified,deno upgrade
doesn't do anything if it's already running the latest release.deno upgrade --output <path>
.- Outputs thedeno
executable to a custom location. If not specified,deno upgrade
overwrites the pre-existingdeno
executable in Deno's default installation directory (e.g. for a user calledadmin
, Deno installs scripts in/home/admin/.deno/bin/
). See theDENO_INSTALL_ROOT
environment variable in table 10-2 for additional details on Deno's installation directory.deno upgrade --version
.- Upgrades Deno to a provided version of thedeno
executable. If not specified,deno upgrade
upgrades Deno to the latest Deno release.
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.