Deno v1.21がリリースされました。
この記事では新機能や修正点などについて解説します。
deno check
コマンドの導入
新しいコマンドとしてdeno check
コマンドが追加されました。
挙動としては基本的にdeno cache
コマンドと同等で、与えられたモジュールの型チェック及びリモートモジュールのダウンロードを行います。
$ deno check mod.ts
deno cache
コマンドとの違い
deno cache
コマンドとの大きな違いとして、deno check
コマンドはデフォルトではリモートモジュールの型チェックを行いません。
deno check
コマンドでリモートモジュールの型チェックも行いたい場合は--remote
オプションを指定する必要があります。
deno run
コマンドでの型チェックについて
deno check
コマンドの追加による影響として、将来的にdeno runコマンドではデフォルトで型チェックが行われなくなる予定です。(Deno v1.21時点でもDENO_FUTURE_CHECK=1
環境変数を設定することで、この挙動を有効化できます)
型チェックを行いたいときは、今回追加されたdeno check
コマンドまたはdeno run --check
で明示的に行う必要が出てきます。
新しいサブプロセスAPI (unstable)
DenoにはDeno.run()
というサブプロセスを生成するためのAPIがありますが、今回、新しく3種類のAPIが追加されました:
Deno.spawn()
(高レベル)Deno.spawnChild()
(低レベル)Deno.spawnSync()
(Deno.spawn
の同期版)
これらのAPIの利用にはDeno.run()
と同様に--allow-run
パーミッションが必要です。
また、これらのAPIの追加により、Deno.run()
は非推奨化される予定のようです。
Deno.spawn()
これは高レベルAPIという位置づけです。
指定したコマンドを実行し、そのコマンドの実行結果(status
)や標準出力(stdout
)及び標準エラー出力(stderr
)への出力内容を返却してくれます。
const { stdout, status } = await Deno.spawn("echo", {
args: ["foo"],
});
console.assert("foo\n" === new TextDecoder().decode(stdout));
console.assert(status.success);
コマンドの出力結果のみが必要で、細かな制御はいらない場合に便利かと思います。
Deno.spawnChild()
こちらは低レベルAPIという位置づけです。
Deno.Reader
/Deno.Writer
ではなくReadableStream
/WritableStream
をベースに実装されています。
const child = Deno.spawnChild("deno", {
args: ["--version"],
});
for await (const output of child.stdout.pipeThrough(new TextDecoderStream())) {
console.log(output);
}
プロセスの実行結果を確認したいときは、status
プロパティを利用できます。
const child = Deno.spawnChild("deno", {
args: ["fmt", "sample.js"],
});
const status = await child.status;
console.assert(status.success);
.output()
を使うことで、Deno.spawn()
と同様に出力内容やステータスなどを取得できます。
const child = Deno.spawnChild("gh", {
args: ["issue", "list"],
});
const { stdout, status } = await child.output();
console.assert(status.success);
console.log(new TextDecoder().decode(stdout));
また、Deno.run
とは異なり、.close()
によって明示的にプロセスを閉じる必要がなくなっています。
Deno.spawnSync
使い方はDeno.spawn()
と基本的には同じですが、こちらは同期的に実行結果を返却します。
const { stdout, status } = Deno.spawnSync("echo", {
args: ["baz"],
});
console.assert(status.success);
console.assert("baz\n" === new TextDecoder().decode(stdout));
deno lsp
の改善
deno.json(c)
で定義されたタスクの実行をサポート- vscode-denoを入れておけば、
Tasks: Run Task
でタスクを実行できます
- vscode-denoを入れておけば、
- ワークスペース内の特定ディレクトリでのみLSPを有効化できるようになりました (
"enablePaths"
オプション) - vscodeのTesting APIがサポート
Testing: Focus on Test Explorer View
コマンドを実行すると、テストケースの一覧を表示できます
deno test
の改善
TestContext
オブジェクトにテストケースに関するメタデータが追加されています。(name
, origin
, 及びparent
プロパティ)
Deno.test("math", async (t) => {
assert(t.name === "math");
assert(t.origin === Deno.mainModule);
await t.step("sum", (t) => {
assert(t.parent.name === "math");
assert(t.name === "sum");
assert(6 === sum(1, 2, 3));
});
});
また、テストケースの実行時にconsole.log
などで出力された内容の取り扱いも改善されています。
具体的には、以下のように出力内容がフォーマットされて表示されます。
$ deno test sample_test.js
running 1 test from ./sample_test.js
foo ...
------- output -------
{ message: "foo" }
baz
----- output end -----
ok (6ms)
test result: ok. 1 passed; 0 failed; 0 ignored;
0 measured; 0 filtered out (21ms)
また、テストケース中でエラーが発生した際のレポート内容も改善されています。
その他にも、deno_std
へのtesting/bdd.tsやtesting/mock.tsモジュールの追加なども行われており、テストを記述する際の利便性が向上しています。
deno fmt
とdeno lint
でインクリメンタルなキャッシュがサポート
deno fmt
とdeno lint
の高速化のため、これらのコマンドの実行結果をインクリメンタルにキャッシュする仕組みが導入されました。
内部的にはSQLiteを使用してキャッシュの仕組みが実装されており、以下のファイルにデータベースが保存されます。
$DENO_DIR/fmt_incremental_cache_v1
(deno fmt
の実行結果)$DENO_DIR/lint_incremental_cache_v1
(deno lint
の実行結果)
また、deno fmt
で.git
ディレクトリを無視する修正も行われており、これらの変更により、大幅なパフォーマンスの向上が見込まれるようです。
deno bench
の改善
Deno v1.20で実装されたdeno bench
の改善が行われています。
大きな変更点としてn
オプションとwarmup
オプションが削除されています。
今後は、Deno本体が信頼のある結果を得られるまで繰り返しベンチマークを実行してくれます。
Deno.bench("URLPattern", () => {
const pattern = new URLPattern({ pathname: "/users/:id" });
pattern.test("http://locahost:3000/users/123");
});
またレポートの出力内容が大幅に改善されており、結果が見やすくなっています。
benchmark time (avg) (min … max) p75 p99 p995
-------------------------------------------------- -----------------------------
URLPattern 210.77 µs/iter (198.87 µs … 634.98 µs) 208.06 µs 293.66 µs 314.84 µs
その他にも、ベンチマークのグループ化もサポートされています。
group
オプションによってグループを定義することができ、これにより、同じgroup
内のbaseline: true
が指定されたケースに対する相対的なパフォーマンスが報告されます。
Deno.bench({
name: "add",
group: "math",
baseline: true,
fn: () => {
add(1, 2);
},
});
Deno.bench({
name: "sum",
group: "math",
fn: () => {
sum(1, 2, 3, 4, 5);
},
});
レポート:
benchmark time (avg) (min … max) p75 p99 p995
------------------------------------------------- -----------------------------
add 169.17 ns/iter (157.29 ns … 249 ns) 169.19 ns 221.56 ns 246.76 ns
sum 192.72 ns/iter (187.26 ns … 255.52 ns) 193.52 ns 228.4 ns 230.39 ns
summary
add
1.14x times faster than sum
reportError()
のサポート
reportError()がサポートされました。
このAPIを使用することで、明示的にUncaught errorを発生させることができます。
また、reportError()
で報告されたエラーは"error"
イベントで補足できます。
addEventListener("error", e => {
console.error(e.error);
e.preventDefault(); // これを呼ばないとexit code=1で終了する
});
reportError(new Error("foo"));
deno repl
の改善
REPL内で新しくclear()
関数が利用できるようになりました。(挙動はconsole.clear()
と同等です)
また、--eval-file
オプションが追加され、REPLの起動前に読み込みたいファイルを指定できるようになりました。
$ deno repl --eval-file=sum.js
Deno 1.21.0
exit using ctrl+d or close()
> sum(1, 2, 3)
6
その他にも、REPL内でimportされたモジュールの型チェックが無効化されるように変更されています。
Deno.Listener
にref
とunref
メソッドが追加 (unstable)
unref()
が呼ばれたListener
はプロセスの終了をブロックしなくなります (タイマにDeno.unrefTimer
を呼んだときと同様の挙動をします)
これらのAPIはdeno_std/node/netでのServer.ref()
やServer.unref()
の実装で利用されています。
DENO_NO_PROMPT
環境変数のサポート
DENO_NO_PROMPT
環境変数がサポートされました。
この環境変数を設定すると、Deno v1.19で有効化されたプロンプトの挙動を無効化できるようになりました。(--no-prompt
を指定したときと同様の挙動です)
その他の変更点
deno run
やdeno cache
の引数に// @ts-check
コメントが付与されたJavaScriptファイルを指定した場合、型チェックが行われない問題が修正されています。