🤗

Deno がもうそこまで来ているらしいので、始めてみた。

2023/10/18に公開

はじめに

「"Deno"分からないとイケてないエンジニア認定されている時代が来るかも...」なんて話を社内で聞きました。
実際に MDN でも Node.js と並んで Deno がいるではありませんか。

そこで慌ててチュートリアルをしたり GraphQL サーバーを作ったりしつつ Deno とはどんな Runtime なのか、Node.js と比較してみました。

TL;DR

Deno は以下の特徴を持つ JavaScript、TypeScript そして WebAssembly のランタイムである。

  • TypeSciprt を JavaScript や WebAssembly と同じように、特に追加でインストールしたり設定したりすることなく利用できる。
  • TypeScript の型の恩恵を受けつつも、型チェックのオーバーヘッドをなくす工夫がされている
  • url import を採用しており、dependencies を分散的に管理できるようになっている
  • ファイルの読み込みやネットワークへのアクセス制限といったセキュリティ制御を Runtime レベルでしてくれる

Deno のはじめ方

https://docs.deno.com/runtime/manual/getting_started/installation#download-and-install
を参考に Deno を起動してスクリプトを実行してみます。

インストール方法

以下のコマンドで Deno をインストールします。

# macOS, Linux
curl -fsSL https://deno.land/x/install/install.sh | sh

# Windows (PowerShell)
irm https://deno.land/install.ps1 | iex

開発環境の設定 (VSCode)

Deno という VSCode 拡張機能をインストールします。
https://marketplace.visualstudio.com/items?itemName=denoland.vscode-deno

その後 VSCode の Command Palette (cmd + shift + P) から Deno: Initialize Workspace Configuration を実行し Deno の開発環境をセットアップします。
こうすることで、Language Server に接続され補完などが有効化されます。

※ Node.js など他のランタイムを使いたい時には "deno.enable" フラグを False に設定する必要があります。

実行してみる

Deno では複数のスクリプト取得方法があります。

  • path を指定する deno run main.ts
  • URL を指定する deno run https://mydomain.com/main.ts
  • 標準入力を利用する cat main.ts | deno run -

URL を指定する方法で Deno by Example にある hello world を実行してみます。

deno run https://examples.deno.land/hello-world.ts
Hello, World!

では次に file を読み込むサンプルを実行してみます。

# reading-files サンプルで読み込む対象の hello.txt を作成する
echo "Hello from local!" > hello.txt

deno run https://examples.deno.land/reading-files.ts

すると

┌ ⚠️  Deno requests read access to "hello.txt".
├ Requested by `Deno.readFile()` API.
├ Run again with --allow-read to bypass this prompt.

というような警告文が出ます。
Deno ではデフォルトでファイルやネットワークなどにアクセスできないようになっており、コマンド実行時に明示的にアクセスを許可する必要があります。

deno run --allow-read https://examples.deno.land/reading-files.ts

警告文の通りファイルの読み込みを許可すると無事実行できます

Read 5 bytes
Seeked to position 6
Read 2 bytes

Modules について

Deno では現在以下の機能を標準ライブラリとして提供しています。
https://deno.land/std@0.204.0?doc

dotenv や file の読み込み、http サーバーなどが提供されています。

また 3rd party のライブラリも提供されています。
https://deno.land/x

ちなみに Node.js のパッケージへの互換性もあります。
以下の方法で Node.js のパッケージを読み込むことができます。

Node.js との特徴的な違い

上記に加えて、GraphQL サーバーを Deno で作るのに挑戦してみました。
https://github.com/motoya-k/deno-graphql-server-sample
その中で気づいた Node.js との特徴的な違いについて 3 点ほど挙げさせていただきます。

TypeScript の扱い

https://docs.deno.com/runtime/manual/advanced/typescript/overview

上記のページに書かれていますが Deno では TypeScript を JavaScript と同等の言語として扱っています。つまり typesciprt ライブラリをインストールして、tsconfig を書いて ... といった作業が不要になるということです。

また、実行時には型のチェックをスキップするのがデフォルトになっています。
https://github.com/denoland/deno/issues/11340
上記の Issue で議論が繰り広げられていますが、要点としては「型は開発時には嬉しいが、実行時にはチェックする必要ないよね」ということです。
この仕様により型チェックのオーバーヘッドなく実行することができます。

ちなみに

deno check https://examples.deno.land/reading-files.ts

のように check コマンドで型チェックはできます。

ライブラリの Import の仕方

Deno では中央集権的に dependecies を管理する必要がなくなっています。
つまり 3rd party アプリに関しても、利用者がすべての dependecies を把握する必要がなくなります。
また URL を指定して実行するので実行者側で手元にダウンロードする必要がないという特徴もあります。(node_modules 的な存在が不要になっているということです。)

とはいっても url import だとファイルそれぞれで import を書く必要があるので手間です。
そこで Deno では Import Maps という機能が提供されており、deno.json 上で import を集約することができます。

deno.json
{
  "imports": {
    "fmt/": "https://deno.land/std@0.204.0/fmt/"
  }
}
main.ts
import { red } from "fmt/colors.ts";

Security に対してのアプローチ

実行する際に --allow-read をつけないとファイルが読め込めないという例がありました。そのほかにもいくつかピックアップすると Deno では以下のようなオプションがあります。

option 説明
--allow-env={ENV_NAME} 環境変数へのアクセス許可
--allow-net={IP/HOSTNAME} ネットワークへのアクセス許可
--deny-write={FILE_PATH} ファイルへのアクセスを拒否

ちなみに -A --allow-all ですべてのアクセスを許可することもできます。

https://docs.deno.com/runtime/manual/basics/permissions#permissions-list

このアプローチは dependecies に対してすべてのアクセスを許可している Node.js とかなり違うポイントになります。

感想

実は GraphQL サーバー を作る中で PostgrSQL 周りで困ったりしました。いい感じに基盤はできていますが、まだまだ枯れてはいない感じで参加するには面白そうな感じがします。

また、Runtime にセキュリティが考慮されていたり URL で実行できたりするので Edge computing やイベント駆動アーキテクチャと組み合わせると使い心地が良さそうに思いました。AWS Lambda や CloudFront とかで導入されるのが楽しみです。

とはいえ、実際はインフラレベルでセキュリティは制御する気もするので、どんな感じで活用するのがベストプラクティスなのかは引き続きウォッチしていきたいです。

Discussion