PC上でJavaScriptを実行できるJavaScript実行エンジンではNode.jsが最も普及しています。これは十分高速であるため、サーバー用途でも利用されています。しかし、Node.jsの作者は2018年より新たなJavaScript実行エンジンDenoを開発しています。DenoはNode.jsの反省より生まれたプロジェクトで多くの点でNode.jsを改良したものです。期待のDenoはNode.jsと比べて何が良いのか実際にプログラムを作って試してみましょう。

  • DenoでWebサーバーを実装して実行したところ

    DenoでWebサーバーを実装して実行したところ

DenoはNode.jsの反省から生まれた

Node.jsの作者として有名なライアン・ダール氏は、2018年にJavaScriptの国際的なカンファレンス「JSConf 」にてDeno(読み方:ディーノまたはデノ)を発表しました。しかも、それは「Node.jsに関する10の反省点」というタイトルで発表されました。とても興味深いタイトルなので興味を惹かれます。具体的には、以下の点が指摘されました。

  • APIの設計において非同期処理に使うpromiseを使用しなかったこと
  • 古いGYPビルドシステムを採用したこと
  • パッケージ管理において設定ファイルのpackage.jsonとnode_modulesを採用したこと
  • モジュールのインポートで拡張子を除外したこと
  • index.jsによりモジュール依存関係の解決を採用したこと
  • JavaScriptのコアエンジンV8によるサンドボックス環境を破壊するような実装をしたこと

実際のところ、Node.jsに詳しくない人には、よく分からない内容だと思います。これらの点は、普段から使っている人であれば「確かに」と納得できる点でした。筆者もよくNode.jsを使うのですが、上記の問題に悩まされたことがあります。

それで、DenoではNode.jsが抱える上記の点を改善すべく開発されています。もちろん、Node.jsの欠点を解決するためだけでなく、生産的で安全なスクリプト環境を目指して開発されています。興味深いことに、当初Go言語で実装されていましたが、高速化のためにRustで再実装されたという経緯があります。こうした現代的な言語の影響を受けて、標準ライブラリやツールが開発されました。

とは言え、重要な点ですが、Denoの全てが独自に作られているわけではありません。Node.jsと同様に基本的なJavaScriptの実行エンジンには、Google Chromeで使われているV8が採用されています。また、ノンブロックキング処理(非同期処理)が基本であるという点も同じです。

それでは何が変わったのでしょうか。DenoがNode.jsと大きく異なるのは次の点です。

  • TypeScriptがデフォルトで利用できるようになった
  • 非同期処理にpromiseを採用して基本的なAPIが再設計された
  • パッケージ管理システムがデフォルトで組み込まれており別途インストールが不要
  • モジュールがES Module方式に統一され、モジュールの扱いがスッキリした
  • ブラウザのJavaScriptとの互換性が向上した

特に、人気のTypeScriptが別途インストールなしに使えるようになったのは大きな点と言えます。そして、Node.jsでの反省を活かして、外部パッケージ(モジュール)の扱いが大きく改善されています。APIがスッキリとしたものに再設計されたのも大きな点です。

とは言え、こうしたコア機能の刷新は、Node.jsで培われた多くの資産が使えなくなることを意味しています。なかなか、Denoの採用が進まないのもそうした点にあります。そこで、今後Node.jsの資産を利用できる仕組みを導入する動きもあります。それでも、Denoもこの原稿執筆時点で、v1.10.3がリリースされており、十分な機能が提供されています。

Denoのインストール

それでは、Denoをインストールして使ってみましょう。Denoのインストールは基本的にコマンドラインから行います。インストールコマンドはDenoのWebサイト「こちら」に記述されています。

WindowsにDenoをインストール

Windowsであれば、PowerShellを起動して以下の一文を入力して、Enterキーを押します。なおPowerShellはWindowsメニューのアプリ一覧より「Windows PowerShell > PowerShell」を選んで起動できます。

iwr https://deno.land/x/install/install.ps1 -useb | iex
  • PowerShellにコマンドを入力するだけ

    PowerShellにコマンドを入力するだけ

インストールが完了したら「deno」と入力して[Enter]キーを押してみましょう。正しくインストールされていれば、次のようにDenoが起動してバージョン情報が表示されます。

  • Denoがインストールされたところ

    Denoがインストールされたところ

macOSにDenoをインストール

macOSでは「ターミナル.app」を利用してインストールします。インストールにはHomebrewを利用します。最初に、こちらからHomebrewをインストールし、その後で、以下のコマンドを実行します。

brew install deno

このように、インストールは非常に簡単です。正しくインストールされていれば、「deno」とコマンドをタイプすると、以下のようにDenoのインタプリタが起動します。

  • macOSにDenoをインストールが完了したところ

    macOSにDenoをインストールが完了したところ

対話環境で遊んでみよう

インストール後、「deno」コマンドを実行すると、Denoの対話環境が起動します。「>」と表示された後ろに、計算式などを入力すると計算が行えます。なお、筆者は頻繁にコマンドライン上で対話環境を起動して電卓の代わりに利用しています。もちろん、普通にJavaScriptが使えるので、変数やループが記述できます。

> (1 + 2 ) * 3
  • 計算を実行したところ

    計算を実行したところ

Webサーバーを起動してFizzBuzz問題を解いてみよう

本連載では、FizzBuzz問題を解いてプログラミング言語の雰囲気を楽しむのが恒例となっています。FizzBuzz問題とは次のようなプログラムです。

> 基本的に1から100までの数字を出力するプログラムを作ってください。その際、3の倍数なら「Fizz」、5の倍数なら「Buzz」、3の倍数かつ5の倍数なら「FizzBuzz」と出力してください。

DenoはTypeScriptが最初から使えるのが特徴です。とは言え、既に本連載では第8回目にてTypeScriptの言語について簡単に紹介しています。

そこで、Denoの機能を利用して、Webサーバーを作成し、その上でFizzBuzzの答えをブラウザに表示するようなものを作ってみましょう。プログラムの前半でWebサーバーを起動し、後半でFizzBuzz問題を解いた答えを表示します。

// --- サーバーを起動 --- (*1)
// モジュールを取り込む
import { serve } from "https://deno.land/std/http/server.ts";
const s = serve({ port: 8080 }); // Webサーバーを起動
console.log("http://localhost:8080/");
for await (const req of s) { // クライアントの接続を待ち受ける
  req.respond({
    headers: new Headers({"content-type": "text/html"}),
    body: getFizzBuzz(100) }); // FizzBuzzの結果を返す
}

// --- FizzBuzzを返す --- (*2)
function getFizzBuzz(max:Number):string {
  const setStyle = (s:string, color:string) => 
    `<div style="background-color:${color};">${s}</div>`;
  const result = []
  for (let i = 1; i <= max; i++) {
    const isFizz = () => i % 3 == 0; // Fizzを判定
    const isBuzz = () => i % 5 == 0; // Buzzを判定
    const isFizzBuzz = () => isFizz() && isBuzz()
    result.push( // FizzBuzzの条件演算子で順次判定
      isFizzBuzz() ? setStyle("FizzBuzz", "#fcf")
        : isFizz() ? setStyle("Fizz", "#fcc")
        : isBuzz() ? setStyle("Buzz", "#ccf")
        : setStyle(String(i), "#eee"));
  }
  return `<div style="text-align:center">` + 
    result.join("") + '</div>';
}

上記のプログラムに「fizzbuzz.ts」という名前を付けて保存します。これを実行するには、コマンドライン上で以下のコマンドを実行します。

deno run --allow-net fizzbuzz.ts

Denoではセキュリティに配慮されており、プログラム起動時に「--allow-net」などのオプションをつけないと、ネットワークやファイルの機能が使えないようになっています。

なお、上記のプログラムでは、ポート8080番でWebサーバーを起動するので、ブラウザを起動してページを確認してみましょう。以下のようにカラフルにFizzBuzzの答えが表示されます。

  • サーバーを起動してFizzBuzz問題を解いたところ

    サーバーを起動してFizzBuzz問題を解いたところ

プログラムを確認してみましょう。(*1)ではWebサーバーを起動します。モジュールを取り込むにはimportを使いますが、このようにURLを記述することで自動でモジュールをダウンロードし取り込んでくれます。そして、awaitを使ってクライアントが接続するのを待ちます。for文の内側にそれぞれのクライアントが接続した時に実行する処理(ここではFizzBuzzの結果)を記述します。for文でWebサーバーの処理が書けるのは圧巻ですね。

(*2)の部分ではFizzBuzz問題を解くプログラムを記述しています。TypeScriptは柔軟な文法を扱えるのが特徴ですが、変数の型を指定することで安全にプログラムを記述できます。

Denoまとめ

以上、今回はDenoについて紹介しました。Webサーバーのプログラムを実行してみると分かりますが、簡単なプログラムを書くのに、わざわざプロジェクトを初期化する必要もなく、自動的にライブラリがダウンロードされて実行されました。Node.jsの反省を元に開発されているだけあって、非常にスッキリしたコードが書けることが分かるのではないでしょうか。今後、DenoがNode.jsを置き換えていく場面も増えていくでしょう。引き続き、Denoから目が離せません。

自由型プログラマー。くじらはんどにて、プログラミングの楽しさを伝える活動をしている。代表作に、日本語プログラミング言語「なでしこ」 、テキスト音楽「サクラ」など。2001年オンラインソフト大賞入賞、2004年度未踏ユース スーパークリエータ認定、2010年 OSS貢献者章受賞。技術書も多く執筆している。直近では、「シゴトがはかどる Python自動処理の教科書(マイナビ出版)」「すぐに使える!業務で実践できる! PythonによるAI・機械学習・深層学習アプリのつくり方 TensorFlow2対応(ソシム)」「マンガでざっくり学ぶPython(マイナビ出版)」など。