【祝v1.0公開】TypeScript実行環境「Deno」をインストールから始めてみよう

Node.jsの作者であるRyan Dahlが新たに開発した「Deno(ディーノ)」のv1.0がリリースされました
初めて触ってみたので過程を記事で共有します
![deno18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/63528/3cf61a9c-c5bb-169b-5575-7abba6f52fd2.png)


Denoの特徴は

- 設定なしですぐ動くTypeScriptとJavaScriptの実行環境
- package.jsonの代わりにTSファイルのURLがエントリーポイント
- 標準モジュールが豊富でインストールとキャッシュ管理も自動
- ファイルやネットワークへのアクセスがデフォルトでは禁止されていてセキュア
- コードフォーマッタやテストライブラリも標準装備

[Deno公式サイト](https://deno.land/)

## 最初のコミットはちょうど2年前
インストールの前に、ふと思い立って3,400以上もあるコミットの始まりを探してみました
Ryan Dahlによる最初のコミットは2018/05/14（多分NY時間だと13日）でした
ピッタリ2年目ということで2020/05/14（NYでは13日）をリリース日に決めたのでしょうね
[Init - denoland/deno@f7c5e19](https://github.com/denoland/deno/commit/f7c5e19081920f59ce2006d3255a58fb611b6a17)
![deno6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/63528/00468cfd-8e16-59bb-1bca-d10173954f71.png)
コミットファイルは

- main.go
- main.ts
- package.json
- tsconfig.json

DenoはGolang+TypeScript+package.jsonから始まったんですね
現在はRust+V8で構築されているようです
凄まじい進化を感じます・・・

せっかくなのでコメント欄に記念カキコしておきました
![deno7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/63528/839d159f-a30f-a695-9082-b2c19d7a590e.png)

## インストール

Mac/Linux

```bash:Shell
curl -fsSL https://deno.land/x/install/install.sh | sh
```
MacならHomebrewもいいですね

```bash
brew install deno
```

Windows

```powershell:PowerShell
iwr https://deno.land/x/install/install.ps1 -useb | iex
```


私はWindows10なのでPowerShellを使いました（PowerShellは標準でインストール済み）
だいたい20秒くらいでサクッと終わりました
![deno0.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/63528/02c417c5-b13f-24ff-b3b6-381dea85535c.png)

インストールが終わったらバージョン確認コマンドを打ってみましょう
Vは大文字です

```powershell
deno -V
# deno 1.0.0 
```

## Hello, world!

Denoはコマンドラインで即座にTypeScriptファイルを実行することができます
公式ドキュメント通りに「welcome.ts」を実行してみます

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

10秒くらいダウンロードに時間がかかって結果が表示されました

![deno1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/63528/0351fa34-2769-3852-35a0-37b41c79416f.png)

この点々は一体何なのだ・・・と思ってコピペしてみたら正体がわかりました
`Welcome to Deno 🦕`
PowerShellはサロゲートペアに対応してないようです

ソースコードはどうやって確認できるのか気になりましたが、よく考えたらURLを実行しているだけなのでChromeで開いてみれば良さそうです
[Deno - welcome.ts](https://deno.land/std/examples/welcome.ts)
![deno2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/63528/a1d09b83-c807-7804-2363-1cff64dea8ed.png)
恐竜くんがいました、かわいいですね
パンくずをたどるとわかりますが、他にもサンプルコードが色々あります
[Deno - examples](https://deno.land/std/examples)

## ソースコードのキャッシュ

同じコマンドを再度実行してみたらさっきとは様子が変わりました
![deno3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/63528/0858dca7-ac96-4832-3839-3ab20afc433f.png)
ダウンロードが発生せず、即座に結果が表示されたのです
一度実行したファイルはキャッシュされているのでしょう

`C:\Program Files\deno`あたりにディレクトリがあるのかなーと思って探したけど全く見当たらず
PATHで確認したらユーザーディレクトリ直下に`.deno`ディレクトリがありました
※追記：実はインストール完了時にちゃんとインストール先ディレクトリが表示されていました・・・

![deno4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/63528/ef95b81c-21b2-df1b-de85-31debfd32a71.png)
Denoの本体サイズは35MBくらいなんですね
ちなみにNode.jsは本体28MB+node_modules（npm含む）

ただしここにはキャッシュファイルが見当たりませんでした
ユーザーディレクトリにDenoがいるということは`AppData`が怪しいですね
![deno5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/63528/34971bcf-b04b-e72b-ef30-6df88c3d5617.png)
ありました

```typescript:8645fc194e64a260ce809466851e4586f3adac3e6090ba74445a4a223359becb
console.log("Welcome to Deno 🦕");
```

```json:8645fc194e64a260ce809466851e4586f3adac3e6090ba74445a4a223359becb.metadata.json
{
  "headers": {
    "vary": "Authorization,Accept-Encoding",
    "expect-ct": "max-age=604800, report-uri=\"https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct\"",
    "x-cache": "MISS, HIT",
    "etag": "W/\"bbb\"",
    "access-control-allow-origin": "*",
    "x-deno-warning": "Implicitly using master branch https://deno.land/std/examples/welcome.ts",
    "strict-transport-security": "max-age=31536000",
    "source-age": "18",
    "x-content-type-options": "nosniff",
    "x-github-request-id": "F2A4:7E16:F5937:107258:5EBC7818",
    "x-xss-protection": "1; mode=block",
    "cache-control": "max-age=300",
    "server": "cloudflare",
    "content-type": "application/typescript; charset=utf-8",
    "cf-request-id": "aaa",
    "date": "Thu, 14 May 2020 01:50:20 GMT",
    "expires": "Thu, 14 May 2020 01:55:20 GMT",
    "cf-cache-status": "DYNAMIC",
    "x-cache-hits": "0, 1",
    "x-fastly-request-id": "zzz",
    "x-frame-options": "deny",
    "set-cookie": "__cfduid=xxx; expires=Sat, 13-Jun-20 01:50:20 GMT; path=/; domain=.deno.land; HttpOnly; SameSite=Lax; Secure",
    "cf-ray": "111-NRT",
    "x-timer": "S1589421020.086214,VS0,VE164",
    "via": "1.1 varnish (Varnish/6.0), 1.1 varnish",
    "content-security-policy": "default-src 'none'; style-src 'unsafe-inline'; sandbox",
    "x-served-by": "cache-hnd18736-HND"
  },
  "url": "https://deno.land/std/examples/welcome.ts"
}
```
実行したいファイルのURLをmetadata.jsonのurlから探してマッチしたら同名ファイルのTypeScriptを実行する方式になっているのだろうか・・・と思いながらググってたら便利なコマンドがありました

```powershell
deno info
# Show info about cache or info related to source file
```
![deno8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/63528/0d2c505b-03ea-1753-e631-bf9cf56b4b39.png)
私が見ていたのは`Remote modules cache`でした・・・
コマンド実行の際に参照しているのは恐らく`TypeScript compiler cache`の方です
![deno9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/63528/510cec70-9b35-b234-3bd6-324542ece1f1.png)

```javascript:welcome.ts.js
"use strict";
console.log("Welcome to Deno 🦕");
//# sourceMappingURL=file:///C:/Users/xxx/AppData/Local/deno/gen/https/deno.land/std/examples/welcome.ts.js.map
```
TSファイルをTypeScript compilerでJSに変換した結果を置いてあるようです
これならV8で即座に実行できますね

## ローカルサーバーを立ててみる

VSCodeに公式サイトのコードをコピペしました

```typescript: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" });
}
```
Deno固有のルールにVSCodeが対応していないので2か所エラーが出ます
![deno10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/63528/5eebd8cc-2a16-420b-5f3a-a34a2a4e3cb8.png)
・インポートパスの拡張子をtsにできない（拡張子を消すと、次はモジュールが見つからないエラー）
・async関数内部でしかawaitできない

エラー解消のために公式サイトで紹介されている拡張機能をインストールします
[Deno support for VSCode](https://marketplace.visualstudio.com/items?itemName=axetroy.vscode-deno)
![deno11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/63528/2b467848-3e78-d1bd-396f-b7cd9f155334.png)
インストールするだけではtsファイルをDenoのスクリプトだと判別してもらえないので設定ファイルをserver.tsと同じ場所に`.vscode`ディレクトリを作成して追加

```json:.vscode/settings.json
{
  "deno.enable": true
}
```
ここまでやってVSCodeを再起動するとawaitの方のエラーは消えますが、importの方はローカルにモジュールがないというエラーが残ります
先ほどのキャッシュ領域に`https://deno.land/std@0.50.0/http/server.ts`があれば良いのだろうと想定し以下のコマンドを実行してみました

```powershell
deno install https://deno.land/std@0.50.0/http/server.ts
```
![deno12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/63528/8c32a1a1-2a88-0316-b76c-f085f909c26c.png)
成功したようです
VSCodeを再起動してみたら見事にエラーが消えました！
![deno13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/63528/1ee19561-3a38-9805-30d1-73d9097a7318.png)
ただ、初回実行時に存在しないモジュールは自動でダウンロードされるはずなのでこの工程は無駄ですね・・・
では実行してみます

```powershell
deno run deno_test/server.ts
```
![deno14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/63528/0b2e6839-89c6-0d12-1a15-0303a0c379a1.png)
怒られました・・・
Denoはデフォルトでセキュアに動作するため、ファイルやネットワークへのアクセスが禁止されています
error文に書いてある通りに`--allow-net`フラグを付けて実行してみましょう

```powershell
deno run --allow-net deno_test/server.ts
# http://localhost:8000/
```
次は上手くいったようです！
この時、Windowsだとファイヤーウォールから警告が出るので許可しましょう
![deno15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/63528/be0215c3-49c8-139e-d27b-bd7411cdd203.png)

試しにChromeで`http://localhost:8000/`にアクセスしてみると
![deno16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/63528/a70eac3a-1fe5-22eb-5dfa-11e779adfbc7.png)
テキストが返ってきました
最低限のサーバーが出来上がりです

`req`オブジェクトがbodyやmethodを持っているのでPOST対応も簡単に出来そうですね
![deno17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/63528/12614de1-2a2a-d720-3006-a17073f1ea70.png)
サーバー停止はCtrl+Cを1回だけ入力するだけです
server以外の標準モジュールはここから探せます
[Deno Standard Modules](https://deno.land/std)

## まとめ
TypeScriptで書いてすぐに動くのはメチャクチャ気持ちがいい！
あらゆることが明示的なので、Node.jsの環境設定がわからなくてTypeScriptに入門できてない人たちにも勧めやすいです
Node.jsの取って代わる未来がくるのかどうかはわかりませんが、個人的にはとても気に入ったのでモジュールをOSSで公開するとかでコミュニティに貢献していきたいですね

Denoじゃないですが、TypeScriptでanyになりがちなHTTPリクエストを静的に型検査可能にするOSSを公開しているのでぜひこちらも読んでみてください！
[HTTPリクエストを型安全にする手法とOSS](https://qiita.com/m_mitsuhide/items/68406158d35a14fa0aa2)