Denoでできること

Denoを触りたい、使ってみたいと思っている方に対して、「Denoを使うと何ができるの？」という情報をまとめます。

## Denoとは？

JavaScriptとTypeScriptのランタイムです。
Node.jsやChromeと同様にJavaScriptを実行できるほか、TypeScriptのサポート、安全な実行環境を提供します。
多くのWeb APIをサポートしていることも特徴です。

## Denoの実行方法

`deno run`コマンドで対象ファイルを実行します。TypeScriptのコンパイルは必要なく、直接実行します。

```shell
> deno run ./main.ts
```

ただし、Denoは「デフォルトで安全」なので、実行時にコマンドラインフラグを渡さないと、ファイル読み書き等の権限を与えることができません。

```shell
> deno run --allow-read ./main.ts # 全フォルダへファイル読み込み権限を与える
> deno run --allow-read=. ./main.ts # カレントディレクトリ内に存在するファイルの読み込み権限を与える
```

権限フラグは`--allow-read`以外にも、`--allow-write`（書き込み許可）や`--allow-net`（ネットワークアクセス許可）が存在します。フラグの一覧は`deno run --help`コマンドで確認できます。

## Denoでできること

### CLIツールの作成

CLIツールでなくても、「csvの読み書き」「JSONの整形」「curlの代わり」などの小さいタスクを実行するためのツールとして便利です。

```ts:httpリクエスト
const response = await fetch("https://www.yahoo.co.jp");
const text = await response.text();
console.log(text);
```

```ts:csvの読み込み
import { parse } from "https://deno.land/std@0.113.0/encoding/csv.ts";

const pathToCsv = "./test.csv";
const csv = await Deno.readTextFile(new URL(pathToCsv, import.meta.url));
console.log(await parse(csv));
```

また、`deno install`コマンドで外部CLIツールのインストールが、
`deno compile`コマンドで複数プラットフォーム向けの単一実行ファイルの生成ができます。

### サーバーを建てる

HTTPサーバーも手軽に建てることができます。
標準ライブラリのHTTPサーバーは「`Request`オブジェクトを取って`Respose`オブジェクトを返す関数」として簡単に定義できます。

```ts:HelloWorldサーバー
import { listenAndServe } from "https://deno.land/std@0.113.0/http/server.ts";

listenAndServe(":8000", () => new Response("Hello World\n"));
console.log("http://localhost:8000/");
```

```shell:ファイルサーバー
> deno run --allow-net --allow-read https://deno.land/std/http/file_server.ts
```

また、作成したサーバーは[deno deploy](https://deno.com/deploy/)というDeno直営のサーバーレスサービスから公開することができます。

### テスト

外部ツールなしてテストを書くことができます。
`deno test`コマンドでテストを実行することができます。

```ts:test.ts
import { assertEquals } from "https://deno.land/std@0.113.0/testing/asserts.ts";

const add = (a: number, b: number) => a + b;

Deno.test("Hello Test", () => {
  assertEquals(add(2, 3), 5);
});
```

### コード整形

いわゆる「フォーマッター」「リンター」も付属しています。
フォーマッターは改行等を整理しコードの見た目を整えるもの、
リンターは決められたコードスタイルに従っているかチェックするものです。

```shell
> deno fmt <ファイルパス> # フォーマット
> deno lint <ファイルパス> # リント
```

### バンドル

`deno bundle`コマンドを利用して、コードを1ファイルにまとめることができます。
フロントエンド向けに書いたコードを1ファイルにまとめる時に利用できそうです。

```shell
> deno bundle <ファイルパス>
```

### ドキュメント生成

`https://raw.githubusercontent.com/`など、web上でアクセスできるコードについては、[公式のドキュメントジェネレータ](https://doc.deno.land/)にURLを突っ込むことによって、ドキュメントを自動生成できます。
ローカルでは、`deno doc`コマンドが利用できます。

```shell
> deno doc <ファイルパス>
```

### Node.jsからの移行

#### npmライブラリの使用

Deno向けに書いたコードから、npmライブラリを呼び出すことができます。

```ts
import marked from "https://esm.sh/marked@3.0.4"; // require('markd');と同じ
```

これは、npmライブラリをブラウザから利用するためのサービス（[esm.sh](https://esm.sh/)や[jspm](https://jspm.org/)など）を使っています。Denoはブラウザと互換性があるため、これらのサービスを流用できるというわけです。

#### 既存のNode.jsコードベースからの移行

既にNode.jsで動いているコードをDenoで動かすこともできます。
これには、`--compat`フラグを使用します。

```shell
> deno run --compat --unstable --allow-read <file_path>
```

`--compat`フラグを使用すると、`node_moduls`や`require`、Node標準ライブラリのPolyfillなどに対応し、既存のNode.jsコードがそのまま動きます。
なお、この機能自体はDeno1.15.3で導入されたばかりで、現在も開発が継続されています。正式導入となる（`--unstable`フラグが外れる）までは、動かないコードもあるかもしれません。

まとめると、

- 新規に作成したコードからnpmライブラリを使用したい→[esm.sh](https://esm.sh/)や[jspm](https://jspm.org/)を使用
- Node.js向けに書かれた既存のコードベースをDenoに移行したい→`--compat`フラグを使用し、徐々にDeno向けになるようコードを書き換える

というのがよさそうです。


## まとめ

- Denoは手軽なスクリプトの実行手段としてオススメです。
- もちろん、フレームワークを利用したWebサイト構築も可能です。
- [deno deploy](https://deno.com/deploy/)というDeno直営のサーバーレスサービスを使うと、一瞬でサーバー構築が完了するので便利です！