Chapter 03

Denoとは?

uki00a
uki00a
2022.12.12に更新

DenoはV8 JavaScriptエンジンをベースに実装されたJavaScript/TypeScriptランタイムです。

Node.jsに関する10の反省点」を修正すべく、Node.jsの開発者でもあるRyan Dahl氏を中心に開発が行われています。

Denoの特徴

Denoの特徴を要約すると、以下の点が挙げられます。

  • TypeScriptを標準でサポート
  • パーミッションシステム
  • 生産性
  • Web標準への準拠
  • ES Modulesベースのモジュールシステム
  • npmパッケージのサポート
  • 最新のJavaScript仕様に準拠

これらについて詳しく説明していきます。

TypeScriptを標準でサポート

Denoの大きなメリットとして、TypeScriptをサポートしていることが挙げられます。

Node.jsでTypeScriptを使用したいときは、基本的にtypescriptts-nodeパッケージをnpmでインストールし、tsconfig.jsonを用意する必要があるかと思います。

Denoは標準でTypeScriptをサポートしており、これらのセットアップ作業が不要になります。

例えば、以下のようなTypeScriptファイルがあったとします。

sample.ts
interface User {
  id: number;
  name: string;
}

const user: User = {
  id: 1,
  name: "foo",
};

console.log(user);

Denoでは、TypeScriptファイルをスクリプトとして実行することができます

$ deno run sample.ts

このように、deno runコマンドを使うことで、TypeScriptファイルをトランスパイルし、実行することができます。

また、トランスパイル後のJavaScriptコードはローカルのファイルシステムにキャッシュされるため、2回目以降に同じファイルを実行する際はトランスパイルなどがスキップされます。

型チェックについて

Deno v1.23以降のバージョンでは、deno runコマンドはデフォルトではTypeScriptの型チェックを実行しません。

もし型チェックを実行したい場合は、deno checkコマンドまたは--checkオプションを使用する必要があります。

$ deno check main.ts

$ deno run --check main.ts

パーミッションシステム

Denoはパーミッションシステムを提供しています。

どういうことかというと、例えば、以下のような処理はデフォルトでは一切実行することができません:

  • ファイルの読み書き
  • ネットワークアクセス
  • 環境変数の参照
  • サブプロセスの実行

これらの処理を行うには、Denoを実行する際に明示的に権限を与える必要があります。

例えば、ファイルの読み込みを行いたいときは--allow-read、ネットワークアクセスを行いたいときは--allow-netオプションを指定するといった具合です。

$ deno run --allow-read --allow-net ./sample.ts

この仕組みにより、Denoでは高いセキュリティが期待できます。

生産性

Denoは開発の場面で必要な多くの機能をはじめから提供しています。

  • フォーマッタ(deno fmtコマンド)
  • リンタ(deno lintコマンド)
  • テストランナ(deno testコマンド)
  • APIドキュメントの生成(deno docコマンド)
  • バンドラ(deno bundleコマンド)
  • LSPサーバ(deno lspコマンド)

大抵の作業はdenoコマンドのみで完結するため、ツールの選定やセットアップ、学習などにかかるコストが軽減されます。

ブラウザ(Web標準)との互換性

DenoはWeb標準との互換性が強く意識されており、多くの機能がWeb標準をベースに実装されています。

例)

  • HTTPリクエストを送信したいときはfetch APIを使用します。
  • WebSocketサーバと通信する際はWebSocketオブジェクトを使用します。
  • バイナリデータを扱いたいときはTyped Arrayを使用します。
  • ストリーミング処理を行いたいときはStreams APIを使用します。
  • マルチスレッドで処理したいときはWorkerオブジェクトを使用します。

ES Modulesベースのモジュールシステム

DenoではNode.jsで提供されていたCommonJS形式のモジュールはサポートされていません。

DenoはES Modulesを前提としており、ライブラリを利用したいときは、以下のようにimport文のURLでダウンロード先を指定します。

import { bold, red } from "https://deno.land/std@0.93.0/fmt/colors.ts";

console.log(bold(red("Hello, Deno!")));

スクリプトを実行する際に、Denoはimport文で指定されたライブラリがローカルのファイルシステムにダウンロードされているか確認します。もしダウンロードされていなければ、Denoは自動でそれをダウンロードし、ローカルのファイルシステムへキャッシュします。

一度ダウンロードされたライブラリは削除しない限りローカルにキャッシュされ続けるため、2回目以降の読み込み時はダウンロード自体がスキップされます。

このように、Deno自身がモジュールマネージャのような機能を備えていることもあって、Node.jsにおけるpackage.jsonnpmなどの仕組みは存在しません。

npmパッケージのサポート

詳細についてはnpmパッケージを使用するのページでも解説いたしますが、Denoはnpmパッケージのサポートも提供しています。

大きな特徴として、Denoではnpmパッケージの利用のためにユーザーにnpm installの実行やpackage.jsonなどを要求することはありません。

npmパッケージについてもdeno.land/xで公開されているサードパーティパッケージなどと同様に、Denoの実行時に自動的にダウンロードされ、ローカルにキャッシュされます。

もしDenoの公式のパッケージレジストリであるdeno.land/xに目的を満たすパッケージが見つからない場合は、npmパッケージの使用も検討してみるとよいかもしれません。

最新のJavaScript仕様に準拠

Denoの組み込みAPIや標準ライブラリであるdeno_stdは、PromiseAsync IteratorなどのJavaScriptの最新機能を念頭に設計されています。

Node.jsで重要な役割を果たしていたStreamやEventEmitterなどのAPIは、Denoの本体には含まれません。(これらのAPIはNode.jsの互換レイヤーで提供されます)

Denoのユースケース

DenoはNode.jsと同様に、様々な用途で使用することができます。

例)

  • スクリプティング
  • CLIツールの開発 (deno compileコマンドでシングルバイナリ化できます)
  • バックエンドAPI (Oakなど)
  • フロントエンド開発 (Aleph.js, Fresh, packupなど)
  • Discordボット (Discordeno)