Denoは、V8 JavaScriptエンジン及びRustプログラミング言語に基づいた、JavaScript及びTypeScriptのランタイム環境である。Node.jsの作者であるライアン・ダールによって作成され、セキュリティと生産性に焦点を当てている。ライアン・ダールが2018年に行った講演「Node.jsに関する10の反省点」で発表された。Denoは単一の実行ファイル内でランタイム環境とパッケージ管理システムの両方の役割を明示的に引き受けるので、別途パッケージ管理システムを必要としない。

歴史 
DenoはJSConf EU 2018でのライアン・ダールによる講演「Node.jsに関する10の反省点」で発表された。ライアン・ダールはこの講演において、後悔しているNode.jsの初期設計での決定について言及し、以下の点を挙げている。

 APIの設計でpromiseを使用しないという選択をしたこと
 古いGYPビルドシステムを使用するようにしたこと
 node_modulesとpackage.jsonの採用
 拡張子を除外したこと
 index.jsによる魔法のようなモジュールの依存関係の解決
 V8のサンドボックス環境の破壊

最終的に、彼はDenoのプロトタイプ版を発表し、Protocol Buffersのようなシリアライズツールを使用したメッセージの受け渡しを通じてシステムコールバインディングを実現し、アクセス制御用のコマンドラインフラグを提供することを目指した。

Denoは当初はGoで実装され、特権側 (Goとシステムコールアクセス) と非特権側 (V8) の間のシリアライズにProtocol Buffersを使用していた。しかしながら、実行時間が2倍になることとガベージコレクションの圧力から、コードは直ぐにRustで再実装された。非同期イベント駆動型プラットフォームとしてに代わってが導入され、より高速な「ゼロ・コピー」シリアライゼーション及びデシリアライゼーションのためにが導入されたが、2019年4月にシリアライゼーションの大幅なオーバーヘッドを測定したベンチマークが公開されたことによって、FlatBuffersは同年8月の後半に削除された。

Goの標準ライブラリをモデルとしたDenoの標準ライブラリは、広範なツール及びユーティリティを提供するために2018年11月に作成され、Node.jsの依存関係での爆発問題を部分的に解決した。

概要 
Denoは現代のプログラマのための生産的で安全なスクリプト環境を目指している。Node.jsと同様に、Denoはに重点を置いており、非ブロッキングコアIOユーティリティのセットとそのブロッキング版を提供している。DenoはWebサーバの作成や科学計算に利用することができる。発音はディーノと読む。

Node.jsとの比較 
DenoとNode.jsはGoogle ChromeなどのChromiumベースのウェブブラウザで採用されているV8 JavaScriptエンジン上に構築されたランタイム環境である。どちらも内部イベントループがあり、スクリプトと広範なコマンドラインユーティリティを実行するためのコマンドラインインタフェースを提供している。

DenoがNode.jsと異なる主な点は以下の通りである:
 CommonJSの代わりに、ES Moduleをデフォルトのモジュールとシステムとして使用する。
 ウェブブラウザと同様に、依存関係 (ローカル及びリモート) を読み込むためにURLを使用する。
 リソースを取得するためのパッケージ管理システムが組み込まれているので、npmは不要である。
 キャッシングメカニズムを備えたスナップショットTypeScriptコンパイラを使用することによるTypeScriptのサポート。
 幅広いWeb APIを実装することによるウェブブラウザとの互換性の向上。
 サンドボックスコードを実行するために、ファイルシステムとネットワークアクセスを制御することができる。
 promise、ES6及びTypeScriptの機能を利用するためにAPIを再設計したこと。
 コアAPIのサイズを最小限にしながら、外部に依存関係の無い大きな標準ライブラリを提供すること。
 特権システムAPIを呼び出しとバインディングの使用のために、メッセージ受け渡しチャネルを使用すること。

例 
以下は、読み取り / 書き込み / ネットワーク権限無しの基本的なDenoスクリプトの実行例である (サンドボックスモード):

deno run main.ts

権限を許可する場合は、明示的に対応するフラグを指定することが必要:

deno run --allow-read --allow-net main.ts

スクリプトの依存関係を検査する場合は、infoサブコマンドを使用する:

deno info main.ts

Denoでの基本的なHello worldは以下の通りである (Node.jsと同様):

console.log("Hello world");

Denoはウェブブラウザでは使用できない殆どのDeno固有のAPIにグローバル名前空間を提供する。UNIXのcatコマンドは、以下のように実装することができる:

/* cat.ts */

/* Deno APIs are exposed through the `Deno` namespace. */
const { stdout, open, copy, args } = Deno;

// Top-level await is supported
for (let i = 0; i < args.length; i++) {
    const filename = args[i]; // Obtains command-line arguments.
    const file = await open(filename); // Opens the corresponding file for reading.
    await copy(file, stdout); // Performs a zero-copy asynchronous copy from `file` to `stdout`.
}

上記のDeno.copy関数は、Goのio.Copy関数のように機能する。stdout (標準出力) はWriterに出力され、fileの入力はReaderである。このプログラムを実行するには、ファイルシステムの読み取り許可が必要である:

deno run --allow-read cat.ts myfile

以下はDenoによる基本的なHTTPサーバの実装である:

// Imports `serve` from the remote Deno standard library, using URL.
import { serve } from "https://deno.land/std@v0.21.0/http/server.ts";

const body = new TextEncoder().encode("Hello World\n");
// `serve` function returns an asynchronous iterator, yielding a stream of requests
for await (const req of serve(":8000")) {
    req.respond({ body });
}

上記のスクリプトを実行すると、Denoはリモートの標準ライブラリファイルを自動的にダウンロードしてキャッシュし、コードをコンパイルする。同様に、URLを入力ファイル名として指定することで、明示的にダウンロードせずに標準ライブラリスクリプト (ファイルサーバなど) を直接実行することができる (-Aは全ての権限を有効にするフラグである):

$ deno run -A https://deno.land/std/http/file_server.ts
Download https://deno.land/std/http/file_server.ts
Compile https://deno.land/std/http/file_server.ts
...
HTTP server listening on http://0.0.0.0:4500/

脚注

関連項目 

 Node.js

外部リンク 
 
 

JavaScript
ランタイムシステム
パッケージ管理システム
オープンソースソフトウェア