支援対象地域:札幌、仙台、関東、愛知、関西、広島、福岡


はじめに


近年のJavascriptの発展は目覚ましいものがあり、出てきた当初は「Webページに動きをつける」程度の認識でしかなかったものが、今やフロントエンドの開発も可能なだけではなく、バックエンド側、IOTデバイス、デスクトップアプリも「NodeJS」というランタイム環境で開発できるほどの言語となりました。それだけではなく、CoffeeScriptやTypescriptといった「AltJS」と言われるJavascript独特の癖を補った上位互換の言語まで登場し、今やJavascriptは現代のWeb開発には無くてはならないプログラミング言語と言っても過言ではないでしょう。
今回は、そんなJavascriptの新しいランタイム環境である「Deno」について紹介します。

Denoとは

Denoとは、NodeJSの開発者でもあるRyan Dahl氏が2020年に発表した、新しいTypescript/Javascriptランタイム環境です。Ryan氏は現在のWeb開発環境に照らし合わせるとNodeJSにはいくつかの設計ミスがあった事に言及し、Denoはそれを解決する新しい技術として登場しました。

NodeJSの設計ミスとDenoでの解決方法

問題1・動的型付け言語であること

Ryan氏はNodeJS(のベースとなるJavascript)が「動的型付け言語」であることに設計のミスがあったと言及しました。
動的型付け言語とは、変数、関数の引数、戻り値が、実行した時の値によって動的に変化する言語のことをいいます。Javascript以外にもRubyやPythonなどが動的型付け言語で有名ですね。
動的型付け言語は、事前に変数の型を宣言しなくてもよく、「文字列を代入した変数に再度別の型のデータ(数値など)を再代入する」といったことも可能です。しかし、動的型付け言語は開発者の意図しない挙動をすることがあり、発生したエラーの発見、解消が困難なこともしばしばあり、エラーの解消にリソースが割かれる場合が多くあります。

> const number = '123';
> number * 2;
246

上記のコードは、Javascriptで文字列型の変数を宣言し、四則演算で計算をした例です。
この例では、文字列が代入された変数を算術計算した際に、Javascriptが「文字列型の変数の型を自動的に数値型に変換」しています。このようなことがコードの各所で発生してしまった場合、開発者の意図しない挙動が起こり、プログラム全体に及ぼす悪影響は計り知れません。

解決法1・静的型付け言語のサポート

上記のような問題を解決するため、Denoは「静的型付け言語」であるTypescriptをデフォルトでサポートしました。
静的型付け言語とは、変数、関数の引数、戻り値をプログラムの実行前に予め定義しておく言語のことをいいます。静的型付け言語は予め変数などに型を明確に指定するため、指定をした型以外は受け付けず(例えば、数値型として宣言した変数に文字列を入れることはできません)、開発者の意図しない挙動を防ぐことができます。
また、Typescriptは「型推論機能」も備えており、前後の文脈から型を予想して型付けをしてくれる機能があります。すべての型推論をしてくれるわけではありませんが、推論をしてくれることで開発者の負担を減らしてくれます。
さらに、Typescriptは「null安全性」を持ち、プログラムで頻出するバグであるnullアクセスエラー(例えば、JavaだとNullPointerExceptionが有名ですね)になりそうなコードを予め検出してくれる機能があります。それに加え、VisualStudioCodeのようなエディタは、型の不整合やnullになりそうな可能性のある箇所を事前に指摘してくれるような機能もあり、実行前にほとんどのエラーが取り除かれ、より堅牢なコードを書くことが可能になります。

> const number = '123';
> number * 3
[eval].ts:2:1 - error TS2362: The left-hand side of an arithmetic operation must be of type 'any', 'number', 'bigint' or an enum type.
2 number * 3,
~~~~~~~

上記のコードは、Typescriptで文字列型の変数を宣言し、四則演算で計算をした例です。
1行目で宣言した変数をTypescriptが「文字列型」であると推論をし、2行目の計算の項目で「左側の変数の型は数値型、any型、bigint型、列挙型でなければなりません」というエラーメッセージが発生しました。これは、本来文字列型の計算ができないコードを、Typescriptが適切に検知してエラー処理をしてくれています。Typescriptを採用することで、開発者の意図しない挙動を抑えてくれるため、不具合の起こりにくいより堅牢なコードを書けると言えるでしょう。

問題2・モジュールシステムの仕組み

NodeJSに使用されているパッケージ管理の仕組みにnode_modules、npm、package.jsonなどがあります。
NodeJSが登場するまで、Javascriptという言語にはモジュールシステムというものは存在しなかったため、サード−パーティのライブラリ等を使用するには、依存関係の正しい把握をして適切な順番でインストールしなければ正しく使えない等、開発者の負担になる事象が多くありました。このような事態を解決するため、NodeJsの開発メンバーはJavascriptをサーバーサイド言語としての使用に耐えうるように「CommonJS」という標準の使用を定めるプロジェクトを立ち上げました。
その項目の一つが、モジュールシステムが盛り込まれ、「require/exports」でパッケージをダウンロードする現在のNodeJSで採用されているモジュールシステムの開発、採用です。このモジュールシステムの採用により、ライブラリの使用が従来よりも手軽になり、パッケージ管理システムnpmと併せてこのシステムの元にたくさんのパッケージが公開されるようになりました。しかし、このシステムでは複雑になりすぎる、node_modulesのファイルが膨大になる、インポート時に意図しないパッケージをインポートしてしまう可能性がある等、後々不具合も多く散見されるようになりました。

解決法2・node-modules、npm、package.jsonの廃止

上記の問題を解決するために、Denoではnode_modules、npm、package.jsonを廃止し、ライブラリのインポートも「import/export」で記述されるESModuleをモジュールシステムとして採用しています。

import { serve } from "https://deno.land/std@0.70.0/http/server.ts";

インポート先もNodeJSのようにローカルのnode_modulesを参照するのではなく、インポート先のURLを指定することにより、node_modulesのような膨大なファイル群をローカルに保存しておく必要がなく、よりシンプルなパッケージ管理が可能になっています。

問題3・Promiseを採用しなかったこと

現在のJavascriptには「Promise」という非同期処理の仕組みが備わっています。
非同期処理とは、「ある処理が実行されてから終わるまで待たず、別の処理を並行して行う」ことです。平行して多くの処理が出来るようになるため、効率的なプログラムが書けるようになるほか、Promiseにより、非同期処理のコードが分かりやすくシンプルに書けるようになります。
しかし、NodeJSは2009年に採用していたPromiseを翌年の2010年には採用を止めました。これにより、NodeJSで非同期処理を実装するには、コールバック関数を多用した可読性の低いコードを書かざるを得ない、という事態に陥りました。

解決法3・Promiseの採用

Denoでは標準ライブラリが改められ、ECMAscriptの仕様が反映されたため、非同期関数はコールバックではなく、Promiseが返るようになり、コードの可読性が向上し、スッキリとわかりやすいコードが書けるようになりました。

問題4・セキュリティ面

NodeJSは「fs」「http」のようにファイルやネットワークシステムへのアクセスを標準で提供します。しかし、そういった機能は場合によっては必要ではない時があり、常にファイルやネットワークなどのアクセス権を提供することはセキュリティ上問題があるとRyan氏は言及しました。

解決法4・セキュリティルールの変更

Denoでは例えばファイル実行時にネットワークアクセスが必要な場合は実行時に--allow-netをオプションとして明示的に指定する必要があります。これにより、万が一脆弱性を突かれて攻撃を受けた際にも、指定されている権限がNodeJSよりも少ないことがほとんどであることから、被害は軽減できると言えるでしょう。

今すぐNodeJSからDenoに乗り換えたほうがよいのか?

結論を先に言うと、まだ完全に乗り換える時期ではないでしょう。なぜなら、Denoはnpmを採用していないため、既存のnpmパッケージはほぼ使えません。まだライブラリの数も十分とは言えず、自分で1から書くことになるコードも多いため、今現在ではNodeJSの完全上位互換になってるとは言えず、不完全な部分も多いと言えます。

まとめ

2020年に登場した技術ということもあり、まだまだ発展途上ではありますが、NodeJSの問題点を改善しているDenoは非常に夢のある技術であり、筆者も大変注目しております。この記事が皆さんのJavascript/Typescriptの学習の際の参考になれば幸いです。