deno で遊んでみよう

![Image](https://3.bp.blogspot.com/-h1WdT1D_PfU/UUQ0nInZ8tI/AAAAAAAAO20/HkcRSqNaMvk/s400/Brachiosaurus.png)

### deno とは
deno は Node.js の製作者 Ryan Dahl 氏により開発された TypeScript を標準でサポートするランタイムです。
Node.js のときに得た教訓をもとに設計がされていますが、Node.js と互換性のある実装というわけではありません。
JavaScript のエンジン自体は Node.js と同じく V8 を利用しています。
[公式サイトはこちら](https://deno.land/)

2020-05-13 にめでたく v1.0 がリリースされたので今回ちょっとだけ遊んでみることにします。
[https://deno.land/v1](https://deno.land/v1)

### Node.js との違い
たくさんありますが大きな違いだけ。

- TypeScript が標準でサポートされる
    - 簡単なものであれば tsconfig.json の用意はしなくて良い
- パッケージの取得はソースコードの import 文をもとに deno が実行時に取得する
    - スクリプトはすべて ES Module 方式になっている
    - npm や yarn のようなパッケージマネージャは今の所不要
    - バージョニングは URL をベースに行う
        - [https://deno.land/std@0.50.0/http/server.ts](https://deno.land/std@0.50.0/http/server.ts) など
- ファイルアクセスやネットワークなどのセキュリティフラグがいくつかある
    - 実行時に指定したもの以外は基本的にブロックされる

細かなところは公式サイトをご覧ください。

### セットアップ
deno はシングルバイナリで動作するランタイムなので Github の Releases から取得した zip を展開して得られる実行ファイルをパスの通ったところに配置すれば直ぐに利用ができます。
公式ではこの作業を簡略化するための [deno_install](https://github.com/denoland/deno_install) というプロジェクトが立ち上がっておりワンライナーでインストールが可能です。

- <b>Linux / WSL / MacOS</b>
    - `curl -fsSL https://deno.land/x/install/install.sh | sh`
- <b>MacOS</b>
    - `brew install deno` (確認時点ではLinuxBrewには非対応)
- <b>Cargo</b>
    - `cargo install deno`

インストール後はパスを通したりするよう指示が出たりしますが適切に対処しましょう。
正しくインストールされていればバージョン情報を確認できるようになっています。
TypeScript のバージョンまで出てるのが斬新ですね。

```bash:version
❯ deno --version
deno 1.0.0
v8 8.4.300
typescript 3.9.2
```

### 初めての deno
公式にリモートからコードを取得して直接実行するサンプルが用意されていますので試しに実行してみましょう。

```bash
deno run https://deno.land/std/examples/welcome.ts
```

実行すると下記のような出力を得ます。見たらわかりますが、リモートのURLを直接実行することができ、スクリプトがコンパイルされ実行されていますね。

```bash
❯ 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 🦕
```

今回実行したスクリプトは [https://deno.land/std/examples/welcome.ts](https://deno.land/std/examples/welcome.ts) ですが直接ブラウザで開くとこのように中身を確認できます。
![Image](https://gyazo.com/b744ada92f3e51bcc9ada25370617bf3/thumb/1000)

あっけなく終わってしまいましたが deno のスクリプトを実行する事ができました。
ここまででは Node.js をインストールして サンプルスクリプトを実行したのとあまり大差ないのでもう少し遊んでみましょう。

### deno をより体感する
続いても公式サイトにあるサンプルスクリプトを利用します。(自分好みにスタイルを変更しています)
下記のファイルをダウンロードするか写経して server.ts として保存しましょう。

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

早速実行してみます。

```bash:server.tsの実行結果
❯ deno run ./server.ts
Compile file:///path/to/workspace/server.ts
Download https://deno.land/std@0.50.0/http/server.ts
...
Download https://deno.land/std@0.50.0/bytes/mod.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 listen ($deno$/net.ts:152:22)
    at serve (https://deno.land/std@0.50.0/http/server.ts:261:20)
    at file:///path/to/workspace/server.ts:2:11
```

ぞろぞろとパッケージが取得されていき、実行されるかと思いきやエラーになりました。
これは最初に説明した deno のセキュリティ機構によるもので、`deno run` したときに許可した権限以上の処理ができないようになっています。
今回の場合、サーバーアプリケーションを起動するために必要なネットワークに対する権限が実行時に付与されていないので、権限が足りないよということを指摘されています。

ということで、`--allow-net` をフラグに指定して権限を追加してリトライしてみると今度はうまく起動してくれました。
試しに curl でアクセスしてみると `Hello World` の出力を得ることができます。

```bash:server.tsの実行結果
❯ deno run --allow-net ./server.ts &
http://localhost:8000/
 
❯ curl localhost:8000
Hello World 🦕
```

このようにして無事Webサーバーアプリケーションを deno で作って動作させることができました。

### ライブラリやエコシステムについて

deno には npm や yarn といったパッケージマネージャが現時点では存在していません。
ここまでやってきたように、deno の標準パッケージも含め、必要な外部ライブラリの類はすべて実行時にリモートから取得される仕組みになっています。

加えて、deno では中央集権的なパッケージリポジトリは存在しておらず、代わりにスクリプトが HTTP でアクセス可能な場所に配置されていればそれを利用することが可能なようになっています。そのため、ライブラリの公開や利用については [GitHub Pages](https://github.io/) や [pika.dev](https://pika.dev/) or [jspm.io](https://jspm.io/) などの CDN を利用して手軽に誰でも公開することができます。
これは Node.js において npm が実質的に中央集権的なパッケージリポジトリとなってしまったことに基づく設計だそうで、「Node.jsに関する10の反省点」でも言及されています。



この方式においては npm を探して必要なパッケージを見つけるというスタイルが失われてしまいますが、それを防ぐ取り組みとして [deno.land/x](https://deno.land/x) でパッケージを探せる仕組みが提供されています。これはパッケージそのものをホスティングしているのではなく、あくまで電話帳のような仕組みなので deno.land/x を利用してやりたいことに対応するパッケージを探したりここから利用することができるようになっています。

### まとめ
この度めでたく v1.0 がリリースされた deno でちょっとだけ遊んでみました。軽く触っただけでも Node.js との違いがちょっとだけわかった気がします。今後、3rd Party ライブラリがより充実したりなど、エコシステムが拡充されてくるとより輝いてくるのではないかと期待しています。
何より標準で TypeScript が実行できる状態にあるというのが TypeScript 大好きクラブ 会員としては最高だなーという印象です。

Node.js との棲み分けや移行についてが気になるところですが、少なくとも Node.js のライブラリが今すぐそのまま deno でも使えるというわけでもないので、徐々に両対応するライブラリが出てきたり、deno 専用の革新的な何かが出てきたりすることを期待しています。(deno版のElectronに相当するなにかとか)

これから普段遣いしていくぞというところも v1.0 のお墨付きがあるので、単純に書き捨てのスクリプトを TypeScript で書くという用途においてはもう deno でやったほうが手軽さがあるのではないかな思ったりしました。

> [from Scrapbox 🍵](https://scrapbox.io/dojineko/deno_%E3%81%A7%E9%81%8A%E3%82%93%E3%81%A7%E3%81%BF%E3%82%88%E3%81%86)