Denoについて触ってみた

# Deno

![Deno.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/418022/073fb8cb-e55d-5c33-8cbe-a19182bd43c3.png)


[Deno 公式マニュアル](https://deno.land/)
[Deno GitHub]([https://github.com/denoland/deno](https://github.com/denoland/deno))

## Denoとは

Denoは、V8 JavaScriptエンジン及びRustプログラミング言語に基づいた、JavaScript及びTypeScriptのランタイム環境である。Node.jsの作者であるライアン・ダールによって作成され、セキュリティと生産性に焦点を当てている。
Denoは単一の実行ファイル内でランタイム環境とパッケージ管理システムの両方の役割を明示的に引き受けるので、別途パッケージ管理システムを必要としない。

Wiki引用：[Deno](https://ja.wikipedia.org/wiki/Deno)


## node との違い

* async / await を使用する際、わざわざ async を記述しなくて良い
* npm によるパッケージ管理の必要がない
* デフォルトでセキュア
* TypeScriptがデフォルトでサポート

## 導入

環境：Ubuntu-20.04(WSL2)

```shell

// zip unzipが入っていない人はインストール
$ sudo apt-get install zip unzip

// Denoインストール
$ curl -fsSL https://deno.land/x/install/install.sh | sh


// .bashrc または .bash_profile に以下を書き込む
export DENO_INSTALL="ホームディレクトリ/.deno"
export PATH="$DENO_INSTALL/bin:$PATH"

// 書き込んだ.bashrc または .bash_profileを読み込む
source ~/.bashrc
```

**バージョン確認**

```
$ deno --version

> deno 1.3.1
> v8 8.6.334
> typescript 3.9.7
```

## HelloWorld

```js
console.log("Welcome to Deno 🦕");
```

```shell

$ deno run hello.js

> Welcome to Deno 🦕
```

恐竜が可愛らしい

## HTTPリクエストを使う

axios を使用しようと思ったのですが、
Deno は XHRオブジェクトを持たないため axios を使うことは出来ませんでした。
なので JavaScript 標準の **fetch** を用いて HTTPリクエストを行います。

[OpenWeatherMap](https://openweathermap.org/api) を用いて天気情報を取得してみる。

```js
const BASE_URL = "https://community-open-weather-map.p.rapidapi.com/weather"

const res = await fetch(BASE_URL + "?id=2172797&q=Japan%2CTokyo" , {
  method: 'GET',
  headers: {
    "x-rapidapi-host": "community-open-weather-map.p.rapidapi.com",
    "x-rapidapi-key": "example-api-key-xxxxxxxxxxxxxxxxxxxxxxxxxx",
    "useQueryString": true
  }
});

const body = await res.json();
console.log("地域: ", body.name)
console.log("天気: ", body.weather[0].main)
console.log("最高気温: ", body.main.temp_max - 273.15)
console.log("最低気温: ", body.main.temp_min - 273.15)
```

### 実行

```shell

地域:  Japan
天気:  Clouds
最高気温:  35
最低気温:  33
```

## TypeScriptがデフォルトでサポート

```typescript
for (let i: number = 1; i <= 100; i++) {
  if (i % 3 == 0 && i % 5 == 0) {
    console.log("FizzBuzz");
  } else if (i % 5 == 0) {
    console.log("Buzz");
  } else if (i % 3 == 0) {
    console.log("Fizz");
  } else {
    console.log(i.toString());
  }
}
```

### 実行

```shell

$ deno run fizzBuzz.ts
> Check file:///mnt/c/src/deno/fizzBuzz.ts
> 1
> 2
> Fizz
> 4
> Buzz
> Fizz
...
```


## サードパーティーモジュールを使う

[Deno Third Party Modules](https://deno.land/x) から使用するモジュールを探し出す。

時間処理モジュール **moment.js** を使ってみる。
[deno_moment](https://deno.land/x/deno_moment@1.0.1)

```js
import { moment } from 'https://deno.land/x/deno_moment@1.0.1/moment.ts'
console.log(moment().format('hh:mm:ss'));
```

初回実行時はモジュールのダウンロードが実行される

```shell

$ deno run whatsTime.js
> Download https://deno.land/x/deno_moment@1.0.1/moment.ts
> Download https://deno.land/x/deno_moment@1.0.1/vendor/moment.js
> 12:15:12
```

初回以降はキャッシュされたモジュールから実行される

```shell

$ deno run whatsTime.js
> Check file:///mnt/c/src/deno/whatsTime.js
> 12:05:30
```

## WebServer

stdモジュールでWebサーバを立ち上げる

[std]([https://deno.land/std@0.67.0](https://deno.land/std@0.67.0))

```js
import { serve } from "https://deno.land/std/http/server.ts";
const port = 8080;
const server = serve({ port: port });

for await (const req of server) {
  req.respond({ body: "Hello World" })
}
```

### 実行

```shell

$ deno run server.js
Check file:///mnt/c/src/deno/server.js
error: Uncaught PermissionDenied: network access to "0.0.0.0:8080", run again with the --allow-net flag
    at unwrapResponse (rt/10_dispatch_json.js:24:13)
    at sendSync (rt/10_dispatch_json.js:51:12)
    at opListen (rt/30_net.js:33:12)
    at Object.listen (rt/30_net.js:204:17)
    at serve (server.ts:287:25)
    at file:///mnt/c/src/deno/server.js:3:16
```

エラーが発生してしまいました。
Deno は**デフォルト**で、**ファイルやネットワークへのアクセスを禁止**しているので、
オプションを付与して権限を許可する必要があります。

### 再実行

```
$ deno run --allow-net server.js
> Check file:///mnt/c/src/deno/server.js

$ curl localhost:8080
> helloWorld
```

## Denoを触ってみた所感

### 良かった点
* 導入してからコード実行までがすぐにできた
* デフォルトでTypeScriptとサポートしてる
 

### 微妙な点

* 既存の npm modulesが使えないのとDenoで対応しているモジュールがまだまだなので、現時点では微妙