Denoに今後導入される新機能（2021夏ver）

Denoでは、新機能の導入がgithubのissueやdiscussionで議論されています。

最終的にどんな機能が導入されるかについてはコアチームの決定次第ですが、導入されそうなものを選んでまとめてみました。

# 3か月以内に予定されている変更

https://github.com/denoland/deno/issues/11168 に掲載されています。

https://github.com/denoland/deno/issues/11168

### ネイティブHTTPサーバーの導入

従来JS側で実装されていたサーバーがRustで書き直されます。
正確には、Rust製HTTPサーバーである[hyper](https://docs.rs/hyper/0.14.11/hyper/)を使うようになります。

この変更により、**HTTPサーバーの処理速度がNode.jsを上回ります**。

[ベンチマーク](https://deno.land/benchmarks#http-server-throughput)を見てみると、確かにNode.jsのHTTPサーバーのスループットがDenoネイティブHTTPサーバーのスループットを上回ってますね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678625/698794a9-8fca-bf6a-ac5b-d885ed870412.png)

もともとNode.jsはRyan DahlのC10K問題（HTTPサーバーの処理能力の問題）に対する答えとして作られました。その性能を同じ作者によって作られたDenoが超えていくのは、10年越しの伏線回収みたいで激アツですね。

8月10日公開のv1.13.0で正式リリースされる予定です。それまでの間は`--unstable`フラグを付けて試すことが出来ます。
また、標準ライブラリのHTTPサーバーや、Deno向けサーバーサイドフレームワークの対応も進められています。

関連PR: [#9935](https://github.com/denoland/deno/pull/9935)

### FFIの導入

FFIが導入されます。C言語などの他言語のコードを、Denoから呼び出すことが可能になります。

似たような機能としてネイティブプラグインがありましたが、これは削除されます。

FFIを使用するには`--allow-ffi`フラグを指定する必要があります。これはFFIに対してファイルアクセスなどの細かいパーミッション制御ができないからです。

関連 [#11152](https://github.com/denoland/deno/pull/11152)


### 標準ライブラリに「collection」モジュールが登場

標準ライブラリに、新しく「collection」モジュールが登場します。

主に配列・オブジェクト操作系の関数が収録されています。

既に利用可能になっています。
https://deno.land/std/collections

### 新しいテストAPI

Denoにはテスターが搭載されています。Node.jsで言うjestやjasmineのようなものです。
今までは`Deno.test`というAPIを使用してテストを定義していましたが、このテストAPIを拡張して、並列テスト、テストの階層化が可能になります。

現在検討されているAPIは以下のようなものです。`Deno.test`に与えるコールバック関数の引数を使って、サブテストを実行することが可能になります。

```js
Deno.test("group with subgroup", async (t) => {
  await t.run("subgroup", async (t) => {
    await t.run("case 1", () => {});
    await t.run("case 2", () => {});
  });
});
```

また、テストを階層化することで「全てのテストの前に○○を実行する」「全てのテストの後に○○を実行する」のような事が可能になります。

関連discussion: [#10771](https://github.com/denoland/deno/discussions/10771) 

### 新しいサブプロセスAPI

従来のサブプロセスAPIは`Deno.run`でした。~~`Deno.run`APIはゾンビプロセスを生成する可能性があることや、stdinやstdoutのハンドリングを行う必要がある~~[`Deno.run`の使用法が直感的でない](https://github.com/denoland/deno/discussions/9435)ことや、[生成したサブプロセスをデタッチモードにできない](https://github.com/denoland/deno/issues/5501)ことから、直感的な新しいAPIの導入が検討されていました。

現在、単純で使いやすいAPIと、低レベルで複雑な設定が可能なAPIの導入が検討されています。
ユースケースとしては、

- 「コマンドを実行して出力を受け取るだけ」→単純なAPI
- 「通信しながら長時間実行するサブプロセス」→複雑なAPI

が想定されているようです。

関連issue: [#11016](https://github.com/denoland/deno/issues/11016)

### deno docのリファクタリング

現在、`deno doc`コマンドはターミナル上への出力とjson出力のみサポートされており、HTML出力を利用するには https://doc.deno.land/ を使うしかありませんでした。
deno docのリファクタリングによって、ローカルでのHTML生成を可能にすると共に、wasm化してランタイム上で動かせるようになる見込みです。

関連issue: [deno_doc#111](https://github.com/denoland/deno_doc/issues/111)

### プロセス間のBroadcastChannel

[BroadcastChannel API](https://developer.mozilla.org/ja/docs/Web/API/BroadcastChannel)はブラウザのタブやウィンドウ、Worker間で通信するためのAPIです。DenoではWorker間での通信に利用されています。
このBroadcastChannel APIで、Denoプロセス間の通信が可能になるようです。

現状、プロセス間通信を既存のAPIを使って実装する場合、web socketサーバーや標準入出力などの低レベルなAPIを使う必要があると思います。
これが`new BroadcastChannel()`だけで可能になるのは、結構すごい事なのではないでしょうか。

関連issue: [#10750](https://github.com/denoland/deno/issues/10750)

### deno実行ファイルへの署名

これはタイトル通りですね。deno.exe本体に対してデジタル署名を行うようです。

関連issue: [#575](https://github.com/denoland/deno/issues/575)

### SSL証明書エラーを無視する機能

現在、`fetch()`を使ってSSL証明書エラーがあるサイトと通信することはできません。
SSL証明書エラーがあるサイトと通信することはセキュリティ上の観点から望ましくないという事で、新しい実行時フラグ（`--allow-xxx`のようなもの）を導入し、そのフラグが有効な時だけ通信可能になるようです。

この機能の導入については2018年から議論されていて、やっと導入されるようです。

関連issue: [#1371](https://github.com/denoland/deno/issues/1371)

### `--prompt`フラグをデフォルトで有効化する

Denoでは、ファイルの読み書きやインターネット接続を行いたい場合に`--allow-xxx`のようなフラグを付与する必要があります。
フラグを付与しなかった場合は、エラーが出て実行が終了します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678625/fcf4d3ae-1be0-bc10-0a49-1fb75eeabb10.png)

ここで`--prompt`フラグを渡して実行すると、エラーを出す代わりに、アクセス許可を求めるプロンプトが表示され、プログラムの実行を継続することができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678625/188dc443-4678-9aea-0f65-8e8443f84403.png)

現在検討されているのは、`--prompt`フラグの挙動をデフォルトにしようという案です。
ユーザー入力が求められない環境向けに、`--no-prompt`というフラグも導入される予定です。

関連issue: [#10183](https://github.com/denoland/deno/issues/10183)

### デフォルトでTypescriptの型チェックをスキップ

これはかなり賛否のある機能です。

DenoはTypeScriptを実行できるのですが、そのまま実行しているわけではなく、内部で自動的にJavaScriptへ変換した上で実行しています。変換には、tsc（型チェックを行う低速なトランスパイラ）か、swc（型チェックを行わない高速なrust製トランスパイラ）が利用されています。
変換時に型チェックを行うかどうかは、`--no-check`フラグの有無で選択できます。
現在、デフォルトでは型チェックが行われていますが、これを変更して、**デフォルトで型チェックをスキップするようになります**。
型チェックありで実行したい時には`--check`フラグを渡すことになります。

**賛成派の意見**

- 初心者にとって型チェックは煩わしいだけ
- ほとんどの人はIDEを使用しているので、型エラーがある場合はエディタ上に表示される
- 型チェックにはパフォーマンスの問題がある

**否定派の意見**

- （JSではなく）TypeScriptを書いている以上、型チェックされることを期待している
- 正しいコードを書いていれば型エラーは発生しない
- 型チェックをする前提でCIが組まれている場合、期待通りに動かなくなる
- swcにはまだバグがある

当初v1.12.0で導入される予定でしたが、反対意見が多く、v1.13.0に延期されました。破壊的な変更であり、v2.0まで導入を待つべきだという意見もあります。

個人的には否定派です。（`// @ts-nocheck`や`// @ts-check`の意味が無くなるので）

関連discussion: [#8549](https://github.com/denoland/deno/discussions/8549)
関連issue: [#11340](https://github.com/denoland/deno/issues/11340)

### メタデータファイル

実行時に毎回--allow-readとか書くのは面倒だということで、設定ファイルの導入が検討されています。
[velociraptor](https://velociraptor.run/)というサードパーティ製ツールに近いのかなと思います。

`package.json`とは違い、プログラムのエントリポイントでのみ使われるという雰囲気です。
~~書き方的に、まだ「検討を進める」という段階にあるっぽいですね。~~
まずは`deno lint`や`deno fmt`の設定ファイルとして導入するようです。

関連issue: [#3179](https://github.com/denoland/deno/issues/3179)

# deno deploy関連

[deno deploy](https://deno.com/deploy)は、Cloudflare WorkersのようなエッジCDNワーカーです。
多数の箇所に分散配置されたサーバーでJavaScriptとTypeScriptを実行することが可能で、webサイトのホスティングなどを行うことが出来ます。
年内の正式公開までの間に、いくつか新機能の導入が予告されています。

### Denoランタイムとの互換性向上

これまでdeno deployはdenoランタイムと互換性が無く、ローカルで実行するには`deployctl`というツールが必要でした。
今後その制限がなくなり、deno向けのコードがdeno deployでそのまま動くようになります！
これにより、Deno向けサーバーフレームワークがdeno deployでも利用可能になることが考えられます。
また、deno deploy上で`Deno.readFile()`がgithubリポジトリのファイルを読み込み可能とすることで、denoランタイムとの互換性を向上させるといった事も考えられているようです。

### 複数エッジ間の通信

[BroadcastChannel API](https://developer.mozilla.org/ja/docs/Web/API/BroadcastChannel)はブラウザのタブやウィンドウ、Worker間で通信するためのAPIです。
deno deployでは、分散配置されたサーバー（=エッジ）間の通信を、このAPIを使って行うことができます。
用途としては、リアルタイムなチャットツールなどが思い浮かびます。

# 今後予定されている変更

Denoリポジトリのdiscussionの中に、「デザインミーティング」という名前でコアチームの議事録が掲載されています。

- https://github.com/denoland/deno/discussions/11363
- https://github.com/denoland/deno/discussions/11364
- https://github.com/denoland/deno/discussions/11365
- https://github.com/denoland/deno/discussions/11420
- https://github.com/denoland/deno/discussions/11497

コアチーム内で今後のAPI設計についての方針が話し合われているようです。その中から、導入されそうな新機能を紹介したいと思います。

### JSONインポート

TypeScriptの対応待ちです。10月のTypeScript4.5で対応される見込みであり、Denoに導入されるのはその後です。

### Deno.emit()の強化

`Deno.emit()`はTypeScriptコードをJavaScriptコードに変換する関数です。
Denoでは拡張子（`.ts`, `.js`）付きのimport文が使われますが、`Deno.emit()`は変換の際にimport文の拡張子を変更しません。
変換後のコードをそのまま動かせるように、impot文の拡張子を`.ts`から`.js`に自動で変えるというオプションが検討されています。

関連issue: [#4538](https://github.com/denoland/deno/issues/4538)

### deno info / deno doc サブコマンドをランタイムAPIから使用可能にする

`Deno.info()`や`Deno.doc()`のような関数を導入して、`deno info`/`deno doc`コマンドをランタイムから利用できるようにすることが検討されています。

現状でもサブプロセスを使って`Deno.run({cmd: ['deno', 'info']})`とすれば実行可能ですが、これは`--allow-run`フラグを必要とします。
`--allow-run`フラグを指定すると、`Deno.run()`を使用してDenoに任意のパーミッションを付与することが可能であり、必要以上に大きな権限を与えることになってしまいます。
`--allow-run`フラグ無しでもサブコマンドの実行結果を得られるようにするため、ランタイムAPIへの導入が検討されています。

関連PR: [#10758](https://github.com/denoland/deno/pull/10758)

### FileSystemAccess API

Chromeなどに導入されている[FileSystemAccess Web API](https://developer.mozilla.org/en-US/docs/Web/API/File_System_Access_API)を、Denoにも導入しようとする動きがあります。
Denoの方針としては、

- Web APIで対応できるものは極力Web APIで対応
- Web APIで対応できないものは`Deno.xxx`の形でAPIを提供する

という事になっています。

現在、ファイルアクセス系の関数は`Deno.xxx`の下にありますが、FileSystemAccess APIのサポートに切り替えていくことが検討されています。

関連issue: [#11018](https://github.com/denoland/deno/issues/11018)

### JSXファクトリ関数のデフォルト値を変更

JSXはトランスパイル時に関数に書きかえられます。どの関数に書き換えられるのかは`tsconfig.json`で設定できます。
現在、tsconfigに何も指定しなかった場合は`React.createElement`という関数にトランスパイルされています。これはReactが使われているNode.jsでは便利ですが、Denoにとってはあまり意味がありません。
ということで、このデフォルト値を`h`に変更することが検討されています。

関連issue: [#11186](https://github.com/denoland/deno/issues/11186)

### Web USB API

[Web USB API](https://developer.mozilla.org/en-US/docs/Web/API/USB)が導入予定です。
Web USB APIはJavaScriptからUSB機器の操作を可能にするAPIです。PCに繋いだICカードリーダやマイクロコントローラーなどの機器を操作することができます。
実装は完了していて、CI環境の整備を待っているようです。

関連PR: [#10912](https://github.com/denoland/deno/pull/10912)

### indexed DB

既にlocalStorageとsessionStorageが導入済ですが、これに加えてindexed DBもサポートされる見込みです。
ランタイムにデータベースが組み込まれていてすぐに利用可能というのは、他のランタイムに対してかなりのアドバンテージだと思います。導入が待ち遠しいです。

関連issue: [#1699](https://github.com/denoland/deno/issues/1699)

# v2.0で導入される破壊的変更

Denoではマイナーバージョンアップでの破壊的変更を避けており、2.0へのメジャーバージョンアップ時に破壊的変更が入ります。
2.0へのバージョンアップの時期ですが、「破壊的変更の数が溜まったら」という事になっています。
2.0で予定されている破壊的変更の一覧は、[こちら](https://github.com/denoland/deno/labels/maybe%202.0)で見ることが出来ます。
長くなったのでこの記事では取り上げませんが、いつか一つずつ詳しく紹介出来たらなと思います。


# 感想

Web USBやFileSystemAccessなどのAPIは、一部では「危険なJavaScript」と称され忌避されています。
しかし、実態としては、Denoやブラウザにおいて手動でパーミッションを付与した時にのみ有効化されるものです。
もし、Electronのようなネイティブアプリに全ての「特権」を付与するか、ブラウザのサンドボックス内で何の権限も付与されないかの2通りしか無かったとします。これでは、USBのような特定の権限だけが欲しい時にもファイルシステムへのアクセス権を付与するしかないという事であり、セキュリティの観点から安全とは言えません。
Denoやブラウザのような、サンドボックスを基本として必要な部分のみ特権を与えるセキュリティモデルが広まると嬉しいな、と思いました。