サーバーサイドJavaScriptランタイムの定番として君臨するのが、お馴染みのNode.jsですが、DenoやBunのようなランタイムも近年注目を集めています。

その2つの中でもより高い人気を誇るとされているDenoは、Node.jsに内在する複数のセキュリティ面での問題に対処し、TypeScriptやWebAssemblyのような技術を包括的にサポートしています。

この記事では、Denoの基本、Node.jsやBunとの違い、そして、Denoを使用してシンプルなHTTPウェブサーバーを構築するハンズオンデモをご紹介します。

Denoとは

開発者の面々はJavaScriptに精通するにつれ、ローカルマシンでのプログラミングにその可能性を見出しました。その結果、サーバーサイドランタイム(ブラウザを使用せずにマシン上でJavaScriptコードを実行できる環境)が作り出されています。

Ryan Dahl氏は、この目的のためにNode.jsを開発し、その後、Node.jsを設計する中で遭遇した問題に対処するためにDenoを生み出しました。その顕著な欠陥として、npmのような集中型パッケージマネージャへの依存、標準ライブラリの欠如、デフォルトのセキュリティ設定の甘さなどが挙げられます。

Denoの主な強みは以下の通りです。

  • デフォルトでのセキュリティ強化策:コードがネットワーク、ファイルシステム、または環境にアクセスするためには、ユーザーが明示的に許可を与える必要があります。
  • TypeScriptとWebAssemblyのビルトインサポート:DenoでのTypeScriptやWebAssemblyプログラムの実行は、JavaScriptプログラムを実行するのと同じくらい簡単です。ランタイムにて、JavaScriptと同様にこれらの言語がコンパイルされます。
  • 分散型パッケージマネージャ:npmやBunのパッケージマネージャといったパッケージリポジトリに依存する代わりに、DenoはURLから直接コードをインポートすることができます。この機能は、GitHubリポジトリ、サーバー、CDNなど、依存関係がホストされている場所であれば、どこからでも読み込み可能です。Denoは、さらにアクセスを容易にするスクリプトホスティングサービスも提供しています。
  • ウェブ標準への準拠:Denoは、ブラウザと同じAPIに従うことを目指しています。これは、ブラウザ用に書かれたコードがランタイムに簡単に変換できることを意味します。

SlackNetlifySupabaseのような大企業がDenoを採用しているものの、ウェブ開発者の間での採用はあまり広まっていません。2022年のStack Overflowの調査によると、アンケートに回答した開発者のうち、Denoを使用しているのはわずか1.47%で、46.31%がNode.jsを使用していると回答しています。

Denoで何ができるのか

他のJavaScriptランタイムと同様に、Denoを使うことで開発者はサーバーサイドでJavaScriptを実行することができます。その結果、Denoを使用して、さまざまなプログラミング作業を行うことが可能です。

Denoが最も得意とするのは、ウェブベースのユーザーリクエストに応答するサーバーアプリケーションの開発です。たとえば、本のオンラインショップを作成する場合には、Denoを使用して、PostgreSQLデータベースから情報を取得し、ユーザーが求めるページを構築しブラウザに送信することができます。

また、ターミナル経由でToDoタスクを管理するコマンドラインツールの構築といった、より基本的なプログラミング作業にDenoを使用することもできます。言い換えれば、PythonRubyのような言語と似た感覚でDenoを使用可能です。

DenoとNodeの比較

DenoはNode.jsの改良を目指しており、いくつかの重要な側面でその役目を果たしています。Denoでは、さまざまなコードモジュールに対して細かなアクセス設定を行い、セキュリティを強化することができます。また、ウェブ標準APIコンプライアンスに重点を置いており、開発者はブラウザ側とサーバー側の両方で同じコードを使用可能です。

サーバーサイドのJavaScriptプロジェクトに取り組むチームにとって、DenoはNodeに代わる有力な選択肢となっています。その機能面での類似から、一部の開発者はDenoがNode.jsに取って代わる可能性を信じていますが、実際にその可能性は─複数の側面を鑑みると─決して高いとは言えません。

Node.jsは今最も人気のあるJavaScriptランタイムであり、豊富なパッケージと大規模で活発なユーザーコミュニティを特徴としています。そのリソースを武器に、Node.jsは非常に魅力的なランタイムとして躍進を続けてきました。

対照的に、Denoは新参者です。バージョン1.0のリリースが2020年5月ですので、これの習得に十分な時間を割けた開発者はまだ多くないでしょう。新しいツールの流行までには、学習に関連した遅れが伴うものです。加えて、Denoが比較的シンプルなプロジェクトに大きなメリットをもたらすかどうかは定かではありません。

しかし、金融のような盤石のセキュリティが不可欠な分野でアプリケーションを構築しているのであれば、Denoのセキュリティ性能という意味で、乗り換えを検討するだけの価値はあるかもしれません。

DenoとBunの比較

元StripeエンジニアのJarred Sumner氏が、2022年7月にBunをベータテスト用にリリースしました。BunはDenoよりも実験的なランタイムであり、Denoとは異なり、Node.jsとの広範な下位互換性を持つように設計されています。

Bunはまた、Node.jsやDenoを凌ぐ驚異的な高速性能を誇ります。主な機能は以下の通りです。

  • 優れたエンジン:GoogleのV8 JavaScriptおよびWeb Assemblyエンジンの代わりに、Bunはより高速で効率的なJavaScriptCoreをJavaScriptエンジンとして使用しています。
  • より多くのコード制御:Bunは、JavaScriptよりもコード実行をより制御できる低レベル言語であるZigで書かれています。
  • きめ細かな調整と効率性UP:Bunの開発チームは、コードの効率性を確保するため、開発に際してプロファイリング、ベンチマーク、最適化を優先しています。

Bunはまだ新しいため、トラブルシューティングを支援するコミュニティサポートは比較的少ない印象を受けます。とはいえ、Bunは実験を楽しむという意味で魅力的です。パフォーマンスの向上を特に必要とするチームはBunをプロジェクトに役立てることができるかもしれませんが、ウェブ開発ではパフォーマンス以外の要素が優先されることが多いのも事実です。

Denoの利用を開始する

Denoについて、また他の一般的なJavaScriptランタイムとの比較について少し学んだところで、次はDenoがどのように動作するかを見てみましょう。このセクションでは、HTTPリクエストに対して「Hello from the server!」と応答するシンプルなサーバーをDenoで作成する方法をご紹介します。

Denoのインストール

Denoは、公式ドキュメントにあるインストール手順を使用して、バイナリの実行ファイルとしてPCにインストールすることができます。例えばmacOSでは、brew install denoコマンドが使えます。

Denoの利用を始めるもう1つの方法として、次のようにnpmパッケージとしてインストールすることもできます。

プロジェクトのフォルダ(例えばdeno_example)を作成し、その中でコマンドnpm initを実行します(initが提案するデフォルトのオプションをすべて受け入れると、基本的なpackage.jsonファイルが作成できます)。

アプリケーションを初期化した後、npm install deno-binを実行してDenoバイナリパッケージをインストールします。続いて、npm startでアプリケーションを起動できるように、package.jsonファイルの中身を更新できます。デフォルトのpackage.jsonファイルの「scripts」オブジェクトプロパティに以下を追加します。

"scripts": {
    "start": "deno run --allow-net app.ts",
    "test": "echo "Error: no test specified" && exit 1"
  },

このスクリプトの追加により、Denoがネットワーク特権(--allow-net)でapp.tsモジュールを実行できるようになります。ちなみにDenoでは、ネットワークまたはファイルシステムへのアクセスを明示的に許可する必要があります。

これで、ポートをリッスンし、ユーザーリクエストに応答するapp.tsモジュールを作成する準備ができました。

App.tsモジュールの作成

Denoでは、非常に簡単に基本的なサーバーを作成することができます。まず、app.tsファイルを作成し、以下のコードを貼り付けます。

import { serve } from "https://deno.land/[email protected]/http/server.ts";
serve((_req) => new Response("Hello from the server!"), { port: 8000 });

このコードでは、Deno.land公式サイトにある、server.ts Denoライブラリserve関数を使用しています。このコードには、受信するリクエストを処理するserve関数ハンドラもあります。これがすべてのリクエストに対して「Hello from the server!」で応答します。

serve関数は、利用するポート番号といったパラメータも受け取ります。今回の例ではポート番号8000を使用しています。

次に、npm startを実行してサーバーを起動します。これにより、localhost:8000でリッスンし、リクエストに挨拶で応答するサーバーが起動できます。

Denoサーバーの動作を確認する
Denoサーバーの動作を確認する

サーバーを本格的なAPIに拡張したい場合は、データベース接続を追加する必要があります。Denoコミュニティによって、MariaDB/MySQLPostgreSQLMongoDBなどの一般的なデータベースをサポートするドライバが作成されているので、これも簡単に実行することができます。

まとめ

ランタイムは、信頼性の高い人気のものから、非常に実験的なものまで様々です。どのランタイムを選択するかは、あなたの実際のプロジェクトの要件次第。

Node.jsはありとあらゆるプロジェクトに利用できます。Node.jsのエコシステムは大規模で、幅広いトラブルシューティングのパターンが網羅されています。

Denoには、セキュリティと開発体験の向上という利点があります。同時に、Denoは経験豊富なチームにとっての優れたツールであり、その利点は(馴染みがなかろうと)ランタイムを学習する時間と人件費を上回る可能性があります。

最後に、Bunはほとんどの本格的なプロジェクトにとっては実験的すぎる一方で、個人でのプロジェクトや拡張のために利用する分には楽しいランタイムでしょう。

全体として、DenoはNode.jsの利点とBunの実験的な可能性のバランスを取る選択肢です。Node.jsはあらゆるプロジェクトにとって有用ですが、一方で、Denoは今後ウェブ開発の進化次第で、最前線に立つ存在になるかもしれません。

まだの方は、Kinstaのアプリケーションホスティングをホビープランでお試しください。利用を開始し、すぐにDenoの技術習得に活用することができます。

Jeremy Holcombe Kinsta

Kinstaのコンテンツ&マーケティングエディター、WordPress開発者、コンテンツライター。WordPress以外の趣味は、ビーチでのんびりすること、ゴルフ、映画。高身長が特徴。