作成者別アーカイブ: 池上龍一

Denoを触ってみよう

2020年の5月に、ポストNode.jsなサーバーサイドJavaScriptランタイム Deno のメジャーバージョンがリリースされました。
何はともあれ触ってみましょう!

環境

macOS 10.15.5
シェルはzshです。

Denoの概要

主な機能

https://deno.land/manual/introduction#feature-highlights

  • 標準でセキュア。明示しない限り、ファイル・ネットワーク・環境アクセスができない
    • オプションで有効化します。
  • 標準でTypeScriptサポート
  • 単一実行ファイルとしての提供
    • Denoの実行ファイルそのもののことですね
  • 組み込みユーティリティ。依存性の検査(deno info)、コードフォーマッター(deno fmt)など
    • linterもついてます。
    • テストランナーもついてます。
    • ドキュメントジェネレーターもついてます。
  • Denoでの動作保証のある、レビュー済み標準モジュール
  • スクリプトの単一JSファイルへのバンドル

Node.jsとの違い

https://deno.land/manual/introduction#comparison-to-nodejs

  • npm なし
  • package.json なし
  • 非同期APIはPromiseを返す
    • Node.jsはPromise以前からあるので、デフォルトではコールバックを使います
    • なので、Node.jsとはAPIが異なります
  • ファイル・ネットワーク・環境アクセスに対する明示的な権限が必要
  • キャッチされないエラーで常に落ちる
  • ES modulesを使う
    • require() は使えません

動かしてみよう

インストール

homebrewでインストールできます。

将来的にはバージョンマネージャー(nvmやnodebrewのような)を使うべきかとは思いますが、deno自体がメジャーバージョンとなってから日も浅く、これといった選択肢はまだないように感じます。

❯ brew install deno

REPLでHello, World

Node.jsと同様REPLが使えます。

❯ deno
Deno 1.1.1
exit using ctrl+d or close()
> console.log("Hello, World!")
Hello, World!

deno run コマンドを使うと、ファイルパスやURL(!)からスクリプトを実行できます。
公式から提供されているハローワールドを実行してみましょう。https://deno.land/std/examples/welcome.ts

❯ deno run https://deno.land/std/examples/welcome.ts
Download https://deno.land/std/examples/welcome.ts
Warning Implicitly using master branch https://deno.land/std/examples/welcome.ts
Compile https://deno.land/std/examples/welcome.ts
Welcome to Deno

しれっと実行していますが、DenoはTypeScript標準サポートです。素敵ですね。

また、一度実行したスクリプトはキャッシュされ、 --reload フラグを使わない限り更新されません。
「だから、飛行機に乗っていても動くよ」という記述もあります。
2回目はダウンロードやらコンパイルやらのログが出ません。

❯ deno run https://deno.land/std/examples/welcome.ts
Welcome to Deno 

スクリプトのインストール

deno install コマンドで、任意のスクリプトをシェルから実行できるようにしてくれます。
先ほどのwelcome.tsをインストールしてみます。

❯ deno install https://deno.land/std/examples/welcome.ts
Download https://deno.land/std/examples/welcome.ts
Warning Implicitly using master branch https://deno.land/std/examples/welcome.ts
Compile https://deno.land/std/examples/welcome.ts
Successfully installed welcome
/Users/rikegami/.deno/bin/welcome
Add /Users/rikegami/.deno/bin to PATH
    export PATH="/Users/rikegami/.deno/bin:$PATH"

パスを通せば……

❯ echo 'export PATH="$HOME/.deno/bin:$PATH"' >> ~/.zshrc
❯ source ~/.zshrc

動きました。npmはお役御免なわけですね。

❯ welcome
Welcome to Deno

仕掛けは単純で、先述の deno run コマンドを動かすシェルスクリプトを生成するだけです。

❯ cat /Users/rikegami/.deno/bin/welcome
#!/bin/sh
# generated by deno install
deno "run" "https://deno.land/std/examples/welcome.ts" "$@"

HTTPサーバーを立ててみよう

標準ライブラリの http を使って動かしてみます。

以下のコードを server.ts として適当なディレクトリに保存します。
ライブラリはES ModulesとしてURLでインポートできるので、 npm install や package.jsonに類するものはありません。

// server.ts
import { serve } from "https://deno.land/std/http/server.ts";
const server = serve({ port: 8000 });
console.log("http://localhost:8000/");
for await (const req of server) {
  req.respond({ body: "Hello World\n" });
}

保存したディレクトリで動かしてみます。

❯ deno run server.ts
Download https://deno.land/std/http/server.ts
Warning Implicitly using master branch https://deno.land/std/http/server.ts
Download https://deno.land/std/encoding/utf8.ts
// 中略……
error: Uncaught PermissionDenied: network access to "0.0.0.0:8000", run again with the --allow-net flag
    at unwrapResponse ($deno$/ops/dispatch_json.ts:43:11)
    at Object.sendSync ($deno$/ops/dispatch_json.ts:72:10)
    at Object.listen ($deno$/ops/net.ts:51:10)
    at Object.listen ($deno$/net.ts:155:22)
    at serve (https://deno.land/std/http/server.ts:256:25)
    at file:///Users/rikegami/Development/sandbox/deno-sandbox/server.ts:2:16

依存性を解決した後に怒られました。
Denoは明示的に指定しない限りネットワークアクセス権限がありません
というわけで、 --allow-net フラグをつけて実行してみます。

❯ deno run --allow-net server.ts

初回はちゃんと聞かれました。「許可」します。

動き始めました。

http://localhost:8000/

curlで叩いてみます。

❯ curl localhost:8000
Hello World

いいですね。

まとめ

とりあえず精神でHTTPサーバーを立てるところまでやってみました。
出たばかりなので、(弊社でよく使っている)herokuには公式のbuildpackがまだなかったり、そもそも技術として枯れていなかったりと、商用利用をするのはまだ難しそうですが、将来的にはNode.jsを置き換えていくものになるかもしれませんね。
触った感じはDXがかなりよいので、今後も隙を見て触ってみようと思います。