LoginSignup
20
6

More than 1 year has passed since last update.

Denoに今後導入される新機能(2021秋ver)

Last updated at Posted at 2021-11-29

リリーススケジュール

  • 2021年10月12日: Deno1.15のリリース
  • 2021年11月16日: Deno1.16のリリース
  • 2021年12月16日: Deno1.17のリリース [TypeScript4.5]
  • 2022年1月20日: Deno1.18のリリース
  • 2022年2月17日: Deno1.19のリリース

Denoのリリーススケジュールは基本的にv8のアップデート周期(4週間)と一致するようになっています。
11月に予定されていたDeno2.0は、来年に延期されました。

Denoに今後導入される新機能

前回の記事から大分間が空いてしまいました…
以下に挙げるのは、導入される方向で議論が進んでいるものです。タイトルでは秋verと銘打ってはいるものの、進捗状況次第では導入が来年以降に持ち越されることもあり得ます。
また、ここで取り上げるのはほんの一部です。詳しい変更内容は各リリースのリリースノートを参照してください。

Node.js互換モード

denoにNode.js互換モードが導入されます。
これまで、Node.js向けライブラリの類はesm.shなどの3rd party CDNを利用することで、Denoからも利用できました。しかし、アプリケーション(サーバー等、ライブラリを使う側のコード)はDenoへの移行手段がありませんでした。Node.js互換モードは、こうした既存のコードベースをDenoに移行するための手段として開発されています。

Node.js互換モードを使うには、実行時に--compatフラグを設定することで使用できます。

> deno run --compat --unstable ./main.ts

まだ実験的な扱いであり、--unsableフラグも必要です。
フラグ下では、requirenode_modulespackage.jsonのサポート、node組み込みライブラリのpolyfillの差し込みなどが行われます。
今のところpolyfillが途中なため、一部のモジュールのみ動作します。現時点ではESLintやExpressが動くようになったという状況で、今後はvite、MongoDBドライバー、Mocha、Next.jsなどが動くことを目指してpolyfillを進めていくようです。

この機能はあくまでNode.jsからの移行のためであり、新しいプロジェクトを互換モードで開始する必要はなく、(エコシステム上)移行が十分に進んだら互換モードを削除する方針とのこと。

関連:#12108#12295#12577

deno deployの正式提供

Deno Deployは、JavaScript、TypeScript、および WebAssembly を世界中のエッジで実行する分散システムです 。

以下のような特徴があります。

  • 例えばCloudFront Functionsがリダイレクト等の軽い処理を実行時間制限付きで行うのに対し、deno deployはメインのアプリケーションを全てエッジで実行する
  • deno CLIで利用できるAPIと互換性があり、ローカル開発をDeno CLIで行うことができる
  • GitHub連携を行うとGitHubリポジトリのファイルをローカルファイルのように扱うことができる
  • サーバーの負荷に応じてサーバーが複数建ち、並列でリクエストを捌くことができる
  • 日本では、東京リージョンと大阪リージョンが存在
  • playgroundがある https://dash.deno.com/playground/my-server-example
  • 現在ベータリリース中(正式提供は2021年第4四半期2022年上半期に予定)

今後のアップデートでは、正式リリースに向けてキャッシュ機能が追加される予定です。
また、CLIとの相互運用性、より良い開始フローにも対応していくとのこと。

deno deployのissueレポート用リポジトリによると、長期的には、定期実行ストレージなどのサポートも検討されているようです。

TypeScript 4.5

Deno1.17にてTypeScript4.5が導入されます。

TypeScript4.5によって、以下の機能が利用可能になります。

  • インポートアサーション
  • プライベートフィールドの人間工学的ブランドチェック(#foo in obj構文)
  • .mts .ctsのサポート
  • Awaitedユーティリティ型
  • …他

詳しくはTS4.5のリリースノートを参照してください。

また、TSがインポートアサーションに対応する事によって、DenoにJSONインポートのサポートが追加されます。

deno.jsonの強化

deno.json(deno設定ファイル)にはフォーマッタやリンターの設定、TSのcompilerOptionを書くことができます。将来的にこれを拡張して、import-map、--allowフラグ、タスクランナーを設定できるようにすることが検討されています。

現在検討されている構文は以下のようなものです。

deno.jsonc
// 当該issueから引用
{
  "compilerOptions": { /* tsconfigの内容 */},
  "imports": {
    // import-mapの内容
    "lodash": "https://esm.sh/lodash",
    "fs": "https://deno.land/std/node/fs.ts"
  },
  "permissions": {
    // 権限フラグの設定
    "allow-all": true,
    "allow-env": true,
    "allow-hrtime": false,
    "allow-read": [ ".", "/tmp" ],
    "allow-write": ".",
    "allow-net": "deno.land,nest.land"
  },
  "tasks": {
    // タスクランナー
    "run": "./mod.ts",
    "build": "--allow-read --allow-write ./build.ts",
    "lint": "src/*.ts",
    "test": {
      "args": "--unstable",
      "permissions": { /*権限フラグの設定*/ },
    }
  }
}

また、deno.jsonはコマンドの--congigフラグで指定する必要がありますが、対象ディレクトリから自動で読み取るようにすることも検討されています。

毎回コマンドで権限を設定するのは面倒なので、早く導入されて欲しい所です。タスクランナーはpackage.jsonで設定するnpmスクリプトに近いですね。

関連:#3179#12763#12764#12800#11907

dnt

dntはdeno向けモジュールをNode.js向けに変換するツールです。

さきほど紹介したNode.js互換モードは、Node.js向けに書いたコードをDenoで使うためのものでした。dntはその逆で、Deno向けに書いたコードをNode.jsで使うための物です。
現在は、Denoの組み込み関数をNode.jsでpolyfillする作業中のようです。

deno.landからブラウザ向けのモジュール配信

ブラウザから直接deno.land/stddeno.land/xのモジュールをimportできるようにするという提案が出ています。
現在でもJavaScriptで書かれたモジュールはブラウザからimport可能ですが、TypeScriptもJavaScriptに変換された上で配信されるようになるため、標準ライブラリなどのtsファイルもブラウザにimportできるようになります。
なおJSに変換されるのはブラウザからアクセスされた時だけで、Deno上ではこれまで通りTypeScriptを使うことができます。

関連:dotland#1902

signal系APIの変更・安定

  1. Deno.Signalをenumから文字列のUnion Typeに変更

    これまでDeno.SignalはTypeScriptのEnumによって実装されていました。OSごとに複数のemumを管理するのは冗長だということで、単純な文字列のUnion Typeに変更されました。
    v1.14.0で導入されました。
    関連:#11900

  2. Deno.addSignalListenerの追加
    Deno.addSignalListenerは、Signalが発生した時に実行する関数を設定する機能です。これまではDeno.Signalfor-await-ofで待ち受けるというAPIでしたが、これがイベントベースの形式に変更されました。合わせて標準ライブラリのsignals/onSignalも非推奨化・削除されます。
    v1.16.0で導入されました。

    v1.15.3以前
    for await (const _ of Deno.signal(Deno.Signal.SIGINT)) {
      console.log("SIGINT");
    }
    
    v1.16.0以降
    Deno.addSignalListener("SIGINT", ()=>console.log("SIGINT"));
    

    関連:#11158deno_std#1644

--no-check=remoteフラグの導入

これまでTypeScriptの型チェックは、全てのファイルをチェックするか全くチェックしないかの2択でした。このフラグが導入されると、「外部の依存関係のコードは型チェックしない」という事が可能になります。

関連:#11970#12766

Deno2.0で導入予定の新機能

11月に予定されていたDeno2.0ですが、Node.js互換モードの完成まで延期されました。
ここでは、元々11月に予定されていた2.0リリースで入る予定だった機能を解説します。
2.0はメジャーリリースのため、破壊的変更が入ります。

参考:2.0のダッシュボード2.0リリースプラン

新機能

新しいサブプロセスAPI

現在のDeno.runに代わる新しいサブプロセスAPIとして、Deno.Commandが導入されます。
型定義を見ると、以下のような使用方になると思われます。

使用方(推測)
const res = new Deno.Command("cat", { args: ["./foo.txt"] }).outut();
console.log(res) // catコマンドの出力

これは後方互換性が無い変更ではないなので、2.0より前のリリースで入るかもしれません。

関連:#11016#5501#11618

デフォルトでロックファイルを使用する

deno runコマンドの--lockフラグを使うと、依存モジュールのチェックサムを検証することができます。この動作がデフォルトになります(--lockフラグが無くてもロックファイルを使用する)。

関連:#11971

動的import/Workerの権限をチェックする--allow-import=<allow_list>フラグ

現在、動的importやWorkerの作成には--allow-readフラグや--allow-netフラグが必要です。これらのフラグはallow-read=./foo/,./bar/等の構文で許可を与える範囲を制限することができますが、importするファイル全てを指定する必要があるため、フラグが長くなってしまうという欠点があります。--allow-importフラグを導入することで、エントリポイントに対してimportが許可されているディレクトリを指定することができるようになります。

関連:#8266

NotCapableエラー

ファイルの読み書き時にPermissionDeniedエラーが発生することがありますが、これの原因は

  • Deno自体のサンドボックス機構によって発生したもの(--allowフラグの付け忘れ)
  • OS側の権限不足によって発生したもの(chmodする必要がある)

の2通りあり得ます。どちらによってエラーが発生したのかを区別するため、新たにNotCapableエラーを導入することが検討されています。

関連:#7394

TypeScript関連

実行時の型チェックをオプションにする

現在は、実行時には毎回型チェックが走っています(厳密にいうと毎回チェックされているわけではなく、結果はキャッシュされています)。実行時の型チェックを無効にするには--no-checkフラグを付ける必要があります。
Deno2.0では、フラグ無しの時は従来の--no-checkフラグ付きと同じ動作になり、型チェックを行いたい時は--checkフラグを付けなければいけないようになります。
また、合わせて型チェックのみを行うdeno checkコマンドも導入されます。

デフォルトでは型チェックを行わなくなることに対して、賛成派の意見として以下のようなものを見かけました。(discord等で見かけただけのやつもあります)

  • 型チェックが遅い
  • 初めて使う人にとってはTypeScriptのエラーが分かりにくい
  • IDEを使っていれば、型チェックで出るエラーはエディタ上に表示される
  • 今後のWeb標準との互換のため
  • (Next.jsなど)ESbuild・swcを使用する他のツールは型チェックをしないのが主流になってきている

「今後のWeb標準との互換のため」というのは、今後JavaScriptの仕様にTypeScript構文(またはそれに準ずるもの)が導入されることを見越してのようです。JSの仕様にTS構文が入った場合、ランタイムがコードを実行する時には型チェックを行わないだろうという見方が大きく、そういった今後の仕様に合わせるという意味で型チェックをしないという事です。

一方、反対意見も出ています。

  • 型チェックはキャッシュされるため、遅さを感じるのは初回実行時だけ
  • TSの型エラーが不要な時はJSを使えばいい
  • 全員がIDEを使っているわけではない

このように反対意見が出ているものの、一応この変更を入れる方向で動いているようです。
合わせてdeno test --no-runコマンドも削除されます。このコマンドは型チェックだけを行うコマンドでしたが、--no-checkがデフォルトになると何も実行しないコマンドになってしまうので削除されます。
CI等への影響を考慮して2.0での導入が予定されています。

関連:#8549#11340#11810#11786#11915

デフォルトのtsconfigのみ使用可能にする

tsconfig.jsonのcompilerOptionはコマンドの--configフラグで指定できます。しかし、複数のライブラリがそれぞれ異なるtsconfigを使用している場合はどうでしょうか。ライブラリのユーザーが指定できるのは1つのtsconfigだけなので、異なるtsconfigを持つライブラリを同時に使用できません。
このように、人々が各々のtsconfigを使って開発するとモジュール間に分断が生まれるため、デフォルトのtsconfig以外を使用不可にしようという提案が行われています。
ただし、

  • デフォルトのtsconfigには何を指定すべきか
  • 将来的にデフォルトのtsconfigが変わった場合、移行のために変更前のtsconfigを指定できないと困るのではないか

といった点を検討中なため、まだ導入が確定しているわけではなさそうです。
特に、依存関係の奥深くにtsconfig由来のエラーが出ている場合に対処のしようが無いので、困ってしまいます。この問題に対処するため、次項のような提案も出ています。

関連:#7732#12111

外部コードのTypeScript診断を無視する

外部の依存関係の中からTSエラーが出ている場合、これをユーザーが修正するのは困難です。特に、Deno本体でデフォルトのtsconfigを更新するとライブラリからエラーが出てしまい、更新ができないという問題が実際に発生しています(useUnknownInCatchVariablesの時など)。
こうした状況に対処するため、外部の依存関係から発生したTSエラーを無視するようにするという提案が出ています。
Deno1.17で--no-check=remoteフラグが導入され、2.0でこのフラグを指定した状態がデフォルトになります。

関連:#11970#12766

JSXファクトリ関数をReact.createElementからhに変更

JSXをトランスパイルする時に、どの関数にトランスパイルするかを表すのがJSXファクトリ関数です。現在のデフォルトはReact.createElementですが、そもそもDenoではデフォルトがReactである必要はあまりないため、これをhに変更します。
既にdeno deployはデフォルトがhになっており、これと挙動を合わせる形となります。

関連:#11186

非推奨 or 不要な機能の削除

Deno.customInspectの削除

Deno.customInspectは、Symbol.for("Deno.customInspect")が導入される前に使われていたプロパティで、現在は非推奨になっています。2.0でこれを削除します。

関連:#10929

evalコマンドの--tsフラグを削除する

既に非推奨になっているevalコマンドの--tsフラグが削除されます。削除後は--ext=tsフラグを使用する必要があります。

関連:#12198

JSで実装されているio関数をDeno本体から標準ライブラリに移動する

Deno本体にある関数には、JSのみで実装されているものがあります。Denoの内部で実装するのはOSのシステムコールが必要なものに絞り、rustの呼び出しが不要なものは標準ライブラリから提供することで、ブラウザ互換性が向上します。
既に実装の移動は完了しており、非推奨扱いでDeno本体に残っている関数や型定義が2.0で削除されます。

関連:#9795

ridを使用するDenoメソッドを削除する

Deno.openで開いたファイルハンドラからreadする方法は、直接.read()メソッドを呼ぶ方法と、Deno.read(rid)を使う方法の2種類あります。

const file = await Deno.open(new URL("./test.json", import.meta.url));
const buf = new Uint8Array(1);
file.read(buf); // パターン1
Deno.read(file.rid, buf); // パターン2

ridを直接操作する方法はあまり使われておらず、またバグの原因にもなるため、削除されます。
Deno.read以外に、Deno.writeDeno.fsyncSyncDeno.fsyncDeno.fdatasyncSyncData.fdatasyncDeno.flockDeno.flockSyncDeno.funlockDeno.funlockSyncも同様に削除されます。

関連:#12107

デフォルト値の変更

Worker内でデフォルトでDeno APIを有効にする

現在はデフォルトではWorker内でDeno APIを使うことはできません。使うためには、Workerの作成時に{deno: true}を指定します。

new Worker("./foo.js", {
  deno: true,  // これを指定するとWorker内でDeno APIを使うことができる
});

2.0ではこれがデフォルトで有効になり、無効化するためには{deno: false}を指定するようになります。

関連:#8174

ProcessStatus.signalの引数をnumberからstringに変更

Deno.signal型がenumからstringのUnion型に変更されたのに合わせて、ProcessStatus.signalの引数がnumberからstringに変更されます。
ProcessStatusはDeno.run()で生成したサブプロセスのステータスを表す型で、既にstableな(=マイナーリリースで破壊的変更が無い)APIなので、2.0で変更されます。

関連:#11912

deno runコマンドで拡張子が無いファイルを実行する場合、TypeScriptとして扱う

現在は拡張子が無いファイルはJavaScriptとして扱われています。これをTypeScriptとして扱うように変更します。

関連:#12220

まとめ

上で紹介した以外にも新機能やバグ修正が盛んに行われています。特に第4四半期来年上半期に正式提供とされているdeno deployは、手軽にサーバーを建てる手段として使っていきたいです。

※内容に間違いがある場合はコメントで指摘してもらえると嬉しいです。

20
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
20
6