リリーススケジュール
- 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
フラグも必要です。
フラグ下では、require
、node_modules
とpackage.json
のサポート、node組み込みライブラリのpolyfillの差し込みなどが行われます。
今のところpolyfillが途中なため、一部のモジュールのみ動作します。現時点ではESLintやExpressが動くようになったという状況で、今後はvite、MongoDBドライバー、Mocha、Next.jsなどが動くことを目指してpolyfillを進めていくようです。
この機能はあくまでNode.jsからの移行のためであり、新しいプロジェクトを互換モードで開始する必要はなく、(エコシステム上)移行が十分に進んだら互換モードを削除する方針とのこと。
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
フラグ、タスクランナーを設定できるようにすることが検討されています。
現在検討されている構文は以下のようなものです。
// 当該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/stdやdeno.land/xのモジュールをimportできるようにするという提案が出ています。
現在でもJavaScriptで書かれたモジュールはブラウザからimport可能ですが、TypeScriptもJavaScriptに変換された上で配信されるようになるため、標準ライブラリなどのtsファイルもブラウザにimportできるようになります。
なおJSに変換されるのはブラウザからアクセスされた時だけで、Deno上ではこれまで通りTypeScriptを使うことができます。
関連:dotland#1902
signal系APIの変更・安定
-
Deno.Signal
をenumから文字列のUnion Typeに変更これまで
Deno.Signal
はTypeScriptのEnumによって実装されていました。OSごとに複数のemumを管理するのは冗長だということで、単純な文字列のUnion Typeに変更されました。
v1.14.0で導入されました。
関連:#11900 -
Deno.addSignalListener
の追加
Deno.addSignalListener
は、Signalが発生した時に実行する関数を設定する機能です。これまではDeno.Signal
をfor-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"));
--no-check=remote
フラグの導入
これまでTypeScriptの型チェックは、全てのファイルをチェックするか全くチェックしないかの2択でした。このフラグが導入されると、「外部の依存関係のコードは型チェックしない」という事が可能になります。
Deno2.0で導入予定の新機能
11月に予定されていたDeno2.0ですが、Node.js互換モードの完成まで延期されました。
ここでは、元々11月に予定されていた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より前のリリースで入るかもしれません。
デフォルトでロックファイルを使用する
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由来のエラーが出ている場合に対処のしようが無いので、困ってしまいます。この問題に対処するため、次項のような提案も出ています。
外部コードのTypeScript診断を無視する
外部の依存関係の中からTSエラーが出ている場合、これをユーザーが修正するのは困難です。特に、Deno本体でデフォルトのtsconfigを更新するとライブラリからエラーが出てしまい、更新ができないという問題が実際に発生しています(useUnknownInCatchVariablesの時など)。
こうした状況に対処するため、外部の依存関係から発生したTSエラーを無視するようにするという提案が出ています。
Deno1.17で--no-check=remote
フラグが導入され、2.0でこのフラグを指定した状態がデフォルトになります。
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.write
、Deno.fsyncSync
、Deno.fsync
、Deno.fdatasyncSync
、Data.fdatasync
、Deno.flock
、Deno.flockSync
、Deno.funlock
、Deno.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は、手軽にサーバーを建てる手段として使っていきたいです。
※内容に間違いがある場合はコメントで指摘してもらえると嬉しいです。