Deno v1.37がリリースされました。
この記事では主な変更点などについて解説します。
実験的なパッケージマネージャが実装 (jsr:
URL)
⚠️この機能は実験的機能のようなので、今後、大きな変更が入る可能性があります。
⚠️また、パッケージレジストリがまだ公開されていないため、この機能はまだ利用できない状態のようです。
Deno本体に実験的なパッケージマネージャーが実装されています。
具体的には、以下のようにjsr:
形式のURLを記述することで、Denoがパッケージレジストリと連携してsemverの解決などを行いつつ、パッケージのインストールなどを自動で行ってくれるようです。
import { foo } from "jsr:@foo/some_pkg@1/mod.ts";
例えば、この場合、@foo/some_pkg
パッケージに関するsemverの解決を行うために、まずhttps://${DENO_REGISTRY_URL}/@foo/some_pkg/meta.json
の問い合わせを行い、その内容を元にどのバージョンをインストールすべきか判断されるようです。
従来のhttps:
やnpm:
形式のパッケージと同様に、npm install
などのコマンドの実行は不要で、スクリプトの実行時にDenoが必要に応じてパッケージをインストールしてくれます。
また、パッケージのインストール元レジストリはDENO_REGISTRY_URL
環境変数で変更可能なようです。
ここからは推測になりますが、この機能は、元々、導入される予定であったdeno:
URLに相当する機能だと思われます。
Deno本体がレジストリと連携してsemver解決を行うことで、依存関係の重複問題などを解消しようというのがこの機能の狙いだと思われます。
deno jupyter
Deno本体にJupyter Kernelが実装されました。
以下のコマンドを実行すると、Deno Kernelがインストールされているかどうかを確認できます。
$ deno jupyter --unstable
ℹ️ Deno kernel is not yet installed, run `deno jupyter --unstable --install` to set it up
もしインストールされていなければ、以下のコマンドでインストールできます。
$ deno jupyter --unstable --install
[InstallKernelSpec] Installed kernelspec deno in /path/to/jupyter/kernels/deno
✅ Deno kernelspec installed successfully.
インストールが完了すると、Deno Kernelを利用できます。
$ jupyter console --kernel deno
また、MIMEタイプがキーに設定されたオブジェクトを返す関数をSymbol.for("Jupyter.display")
プロパティに設定することで、出力内容をカスタマイズできます。
In [1]: { [Symbol.for("Jupyter.display")]: () => ({ "text/plain": "Hello Deno!", "text/html": "<b>Hello Deno!</b>" }) }
Out[1]: Hello Deno!
deno test
TAPレポーター
deno test
コマンドにTAPレポーターが実装されました。--reporter=tap
オプションを指定することで有効化できます。
$ deno test --allow-read --reporter=tap | deno run --allow-read npm:tap-nyan@1.1.0
10 -_-_-_-_-__,------,
0 -_-_-_-_-__| /\_/\
0 -_-_-_-_-_~|_( ^ .^)
-_-_-_-_-_ "" ""
Pass!
Deno.test.only()
/Deno.test.ignore()
Deno.test.only()
とDeno.test.ignore()
が実装されました。
それぞれ、Deno.test()
にonly: true
またはignore: true
を指定した際と同様の振る舞いをします。
Deno.test.only("add", () => {
assertEquals(add(1, 2), 3);
});
// これは以下と同様です
Deno.test({
name: "add",
fn: () => {
assertEquals(add(1, 2), 3);
},
only: true,
});
Deno.test.ignore("sub", () => {
assertEquals(sub(5, 2), 3);
});
// これは以下と同様です
Deno.test({
name: "sub",
fn: () => {
assertEquals(sub(5, 3), 3);
},
ignore: true,
});
フィルタリングに関する挙動の改善
--filter
による絞り込みによって実行がスキップされたテストファイルがログに出力されないように挙動が改善されています。
v1.37.0:
$ deno test -A --filter="$fresh-testing-library/components"
running 1 test from ./components.test.tsx
$fresh-testing-library/components ...
provides a thin wrapper to `@testing-library/preact` ... ok (52ms)
$fresh-testing-library/components ... ok (100ms)
ok | 1 passed (1 step) | 0 failed | 9 filtered out (1s)-
v1.36.4:
$ deno test -A --filter="$fresh-testing-library/components"
running 0 tests from ./async-route-components.test.tsx
running 1 test from ./components.test.tsx
$fresh-testing-library/components ...
provides a thin wrapper to `@testing-library/preact` ... ok (57ms)
$fresh-testing-library/components ... ok (108ms)
running 0 tests from ./doc.test.ts
running 0 tests from ./internal/fresh/mod.test.ts
running 0 tests from ./permissions.test.ts
running 0 tests from ./server.test.ts
ok | 1 passed (1 step) | 0 failed | 9 filtered out (1s)
また、--filter
とonly: true
を併用した際の挙動が変更されています。
通常、only: true
が指定されたテストケースが実行された場合、Denoはテスト全体を強制的に失敗として扱います。
Deno v1.37ではこの挙動が一部変更され、--filter
オプションによるフィルタリングの結果、only: true
が指定されたテストケースの実行がスキップされた場合は、通常通りテストの実行を成功として扱います。
例えば、以下のようなテストコードがあったとします。
Deno.test({
name: "add",
fn: () => {
assertEquals(add(1, 2), 3);
},
only: true,
});
Deno.test("sub", () => {
assertEquals(sub(5, 1), 4);
});
このテストを以下のコマンドで実行すると、v1.37では成功しますが、v1.36.4ではエラーが発生します。(error: Test failed because the "only" option was used
)
$ deno test --filter=sub test.ts
running 1 test from ./test.ts
sub ... ok (0ms)
ok | 1 passed | 0 failed | 1 filtered out (33ms)
そのため、意図せずしてonly: true
が設定されたテストケースがコミットされないよう、注意が必要かもしれません。
サニタイザーのパフォーマンス改善
サニタイザーとは、deno test
コマンドがリソースリークなどを検出するための仕組みです。
このサニタイザーの実装を最適化することで、deno test
コマンドのパフォーマンスがかなり改善されたようです。(場合によっては、以前までの10倍程度まで高速化が見込まれるようです)
また、サニタイザーが出力する情報量の増加や信頼性の向上なども行われています。
--coverage
の改善
deno test --coverage
によるカバレッジ計測時に、Denoの内部モジュールに関する網羅率も計測されてしまう問題が修正されています。
deno lsp
入力補完に関する改善
npmパッケージの補完がサポートされました。import
宣言でnpm:
を記述する際に、パッケージ名やバージョンなどが提案されます。
また、自動インポートに関する保管候補にファイル名(パス)が表示されるように挙動が改善されています。
deno.json
の検出時にvscode-denoを自動で有効化
今まで、vscode-denoを有効化するためには、.vscode/settings.json
で"deno.enable": true
を指定する必要がありました。
Deno v1.37では、deno.json(c)
が存在すれば、自動でvscode-deno
が有効化されるように挙動が変更されています。
この挙動を無効化したい場合は、"deno.enable": false
を明示する必要があります。
disablePaths
オプション
disablePaths
オプションが追加されました。
プロジェクト内の特定のディレクトリに対してのみdeno lsp
を無効化したいようなケースで活用できます。
{
// vscode-denoでの設定例
"deno.disablePaths": ["./frontend"]
}
その他の改善
- ファイルをリネームした際に、関連するファイルの
import
の自動的なアップデートがサポートされました。 - 自動importなどの実行時に、
deno.json(c)
のfmt.singleQuote
などのフォーマットに関する設定が適用されない問題が修正されています。 - vscodeのテストエクスプローラーにテストケースを表示する際に、
deno.json
のexclude
/test.exclude
/test.include
の設定が適用されるようになりました。
deno lint
deno lint --rules
で全てのルールが表示されるように挙動が変更されました。(v1.36.4まではrecommended
タグのルールのみが表示されていました)
また、各ルールのタグも表示されるように出力が改善されています。
v1.37.0:
$ deno lint --rules | grep fresh
- fresh-handler-export [fresh]
help: https://lint.deno.land/#fresh-handler-export
- fresh-server-event-handlers [fresh]
help: https://lint.deno.land/#fresh-server-event-handlers
v1.36.4:
$ deno lint --rules | grep fresh
$ echo $?
1
$ deno lint --rules | grep prefer-as-const
- prefer-as-const
help: https://lint.deno.land/#prefer-as-const
Node.js互換性
このリリースでも、様々な改善が実施されています。
具体的には、v1.37で以下のパッケージの動作がテストされているようです。
主な変更点:
node:http2
:http2.connect()
とClientHttp2Session
が実装されました。- ストリーミングや
Trailer
などのヘッダーのハンドリングなど、基本的な操作は機能するようです。 - ただし、
ref()
/unref()
などは未実装のようです。
- ストリーミングや
node:crypto
:createCipheriv()
とcreateDecipheriv()
でaes-128-gcm
及びaes-256-gcm
がサポートされました。node:child_process
:env
オプションにundefined
が設定されたキーがあると、プロセスがクラッシュする問題が修正されています。node:net
: wsなどのパッケージをより効率に扱えるよう、ソケットからの読み込みが最適化されています
ロックファイル v3
ロックファイルの新しいフォーマット(v3)が導入されています。
おそらく、jsr:
URLの導入などに向けた対応と推測されます。
また、再現性の向上のため、HTTPリダイレクトが発生した場合、リダイレクト元とリダイレクト先のURLの組み合わせがロックファイルで管理されるようになりました。
TypeScript v5.2
Deno本体のTypeScriptがv5.2へアップデートされています。
TypeScriptファイル限定ではあるものの、await using
とusing
がサポートされています。
class Disposable {
[Symbol.dispose]() {
console.info("Disposable: disposed!");
}
}
{
using disposable = new Disposable();
}
// => Disposable: disposed!
ただし、以下の機能については、まだ動作しないようです。(v8でのサポート待ちの状況のようです)
- JavaScriptファイルにおける
using
/await using
- Decorator Metadata
CLI
Import Attributesが実装
Import Attributesが実装されました。
import config from "./deno.json" with { type: "json" };
console.info(config);
前身であるImport Assertionsについては、今後、サポートが廃止される予定のようです。
--allow-run
の挙動が改善
--allow-run=<プログラム名>
のように、許可をしたいプログラム名を非絶対パス形式で指定した際の挙動が変更されています。
例えば、--allow-run=deno
のように指定して かつ deno
が/usr/local/bin/deno
に存在した場合、v1.36とv1.37ではそれぞれ以下のような振る舞いをします。
バージョン | コード | 挙動 |
---|---|---|
v1.36 | new Deno.Command("/usr/local/bin/deno") | PermissoinError |
v1.37 | new Deno.Command("/usr/local/bin/deno") | 問題なく動きます |
Deno.Server#shutdown
Deno.Server#shutdownが実装されました。(利用する際は、--unstable
の指定が必要です。)
従来までのsignalオプションを使用した方法と異なり、このAPIを使用することでサーバーをgracefulに停止できます。
このAPIを呼んだ後は、サーバは一切のコネクションを受け付けず、実行途中のリクエストは処理の完了まで待機されます。