はじめに

Deno v2.5がリリースされました。

この記事では主な変更点などについて解説します。

deno bundle

Deno.bundle()APIが追加

deno bundleコマンドの機能をプログラムから利用するためのDeno.bundle()APIが正式にリリースされました (#29949)

Deno.bundle()を利用するためには--unstable-bundleによって明示的に有効化が必要です:

const result = await Deno.bundle({
  entrypoints: ["./mod.ts"],
  platform: "deno",
});
console.assert(result.success);

const [outputFile] = result.outputFiles;
const bundledCode = outputFile.text();
console.assert(typeof bundledCode === "string");

outputPathoutputDirオプションを指定することで、バンドル結果がファイルシステムへ書き込まれます (--allow-writeの指定は不要なようです):

const result = await Deno.bundle({
  entrypoints: ["./mod.ts"],
  platform: "browser",
  minify: true,
  sourcemap: "external",
  outputDir: "dist",
});
console.assert(result.success);

HTMLエントリーポイントのサポート

deno bundleでHTMLエントリーポイントのサポートが追加されています (#29856)

例として、バンドル対象のHTMLとJavaScriptモジュールを準備しておきます。

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
</head>
<body>
  <script type="module" src="./index.tsx"></script>
</body>
</html>
// index.tsx
import { render } from "preact";

function App() {
  return (
    <main>
      Hello Deno!
    </main>
  );
}

render(<App />, document.body);

Preactがきちんと動作するようdeno.jsonに設定を追加しておきます。

{
  "imports": {
    "preact": "npm:preact@10.27.1",
    "@std/http": "jsr:@std/http@1.0.20"
  },
  "compilerOptions": {
    "jsx": "react-jsx",
    "jsxImportSource": "preact",
    "lib": [
      "dom",
      "dom.asynciterable",
      "dom.iterable"
    ]
  },
  "exclude": ["dist"]
}

この状態でHTMLファイルを引数に指定してdeno bundleを実行すると、--outdirディレクトリにバンドル結果が出力されます。

$ deno bundle --unstable-bundle --outdir=dist index.html
⚠️  deno bundle is experimental and subject to changes
Bundled 4 modules in 43ms
  dist/index-2G6XNFTT.js 15.73KB
  dist/index.html        166B

# `deno_std`のファイルサーバー (`@std/http/file-server`) で結果を確認できます
$ deno run --allow-read --allow-net @std/http/file-server dist

deno lint

no-import-prefixルール

no-import-prefixルールが追加されています (#30598)

以下のようにjsr:npm:付きのimportの使用が検出されると、エラーが発生します。

import { delay } from "jsr:@std/async@^1/delay";

deno.jsonまたはpackage.jsonで依存パッケージを管理することを促すためのルールのようです。

no-unversioned-importルール

no-unversioned-importルールが追加されています (#30609)

以下のように、バージョンが明示されていないimportを検出してくれます。

import { delay } from "jsr:@std/async/delay";

deno fmt

引数なしでdeno fmtを実行した際の振る舞いが変更

deno.jsonおよびpackage.jsonが存在しない状態でdeno fmtを実行すると、以下の確認メッセージが表示されるよう挙動が変更されています (#30623)

$ deno fmt
Warning It looks like you're not in a workspace. Are you sure you want to format the entire '/path/to/current-dir' directory? [Y/n]

import/exportへのfmt.spaceSurroundingPropertiesのサポート

deno.jsonにおける"fmt.spaceSurroundingProperties": falseの設定がimportおよびexportにも適用されるよう改善されました (#30371)

{
  "fmt": {
    "spaceSurroundingProperties": false
  }
}
// 1. フォーマット前
import { delay } from "jsr:@std/async@^1/delay";

// 2. フォーマット後
import {delay} from "jsr:@std/async@^1/delay";

deno install/deno add

出力内容の改善

Deno v2.4.5におけるdeno installコマンドの出力の改善に続いて、パッケージのインストールに要した時間やキャッシュから再利用されたパッケージ数なども表示されるよう改善されています (#30615)

$ deno install
Installed 9 packages in 1631ms
Reused 0 packages from cache
Downloaded 9 packages from JSR
+++++++++
Downloaded 0 packages from npm

Dependencies:
+ jsr:@david/dax 0.41.0
+ jsr:@david/which 0.4.1
+ jsr:@std/assert 0.221.0
+ jsr:@std/bytes 0.221.0
+ jsr:@std/fmt 0.221.0
+ jsr:@std/fs 0.221.0
+ jsr:@std/io 0.221.0
+ jsr:@std/path 0.221.0
+ jsr:@std/streams 0.221.0

また、このインストール結果の表示機能を引数付きのdeno installdeno add, deno cacheコマンドなどにも導入する改善が実施されています (#30549)

ライフサイクルスクリプトに関する警告メッセージの改善

ライフサイクルスクリプトを提供するnpmパッケージをインストールした際の警告メッセージが改善されています (#30527)

$ deno add npm:better-sqlite3@12.2.0
Add npm:better-sqlite3@12.2.0
╭ Warning
│  Ignored build scripts for packages:
│  npm:better-sqlite3@12.2.0
│  Lifecycle scripts are only supported when using a `node_modules` directory.
│  Enable it in your deno config file:
"nodeModulesDir": "auto"
╰─

jsrパッケージのインストールに関するバグ修正

deno.jsonでjsrパッケージのバージョンを更新した状態で引数なしでdeno installが実行された際に、該当jsrパッケージの更新後のバージョンをインストールするよう挙動が修正されています (#30483)

deno run/deno task

引数なしで実行した際のタスクの一覧表示機能が再導入

Deno v2.0.0-rc.3で Revert されていた引数なしでdeno runコマンドが実行された際にdeno.jsonで定義されたタスクの一覧を表示する機能が再導入されました (#30592)

タスク名とディレクトリ名の衝突時の挙動が改善

deno run <task>で指定したタスク名と同じ名前のディレクトリが存在する場合、エラーが発生してしまう問題が修正されています (#29538)。この場合、deno.jsonで定義されたタスクの方が実行されます。

--env-file--watchを併用した際の挙動の改善

--env-file--watchの併用時に、.envファイルが変更された際にプロセスの再起動と.envファイルの再読み込みが行われるよう改善されています (#30197)

--preloadで複数のファイルを読み込ませる際の挙動の変更

--preloadオプションにdata:URLを指定できるようにするため、--preloadオプションに複数のファイルをカンマ区切りで指定できないよう挙動が変更されています (#30544)

--preloadオプションで複数のファイルを読み込ませたい場合、今後は--preloadオプションを複数回指定する必要がありそうです。

deno check

主にSvelteKit向けの動作の改善が実施されているようです。

tsconfig.json - compilerOptions.rootDirsのサポート

deno checkコマンドでtsconfig.jsonに記載されたcompilerOptions.rootDirsがサポートされています (#30495)

compilerOptions.moduleResolution: "bundler"のサポート

compilerOptions.moduleResolution: "bundler"がサポートされています。compilerOptions.moduleesnextまたはpreserveが指定された際は、compilerOptions.moduleResolutionのデフォルト値としてbundlerが使用されるよう実装されています (#30603)

deno publish

import.meta.resolve()の取り扱いの改善

静的に解析可能なimport.meta.resolve()の引数が正規化 (unfurl) されるよう改善されています (#30663)

具体的には、パッケージの公開時に以下のような変換が実施されるようです。

// 1. `deno publish`の実行前
import.meta.resolve("preact");

// 2. `deno publish`によるJSRへの公開後 (Import mapsの内容に基づいて、specifierが正規化されます)
import.meta.resolve("npm:preact@10.27.1");

deno lsp

ワークスペースメンバーの取り扱いの改善

ワークスペース内のメンバーのImport mapsで定義されたエントリーへのauto importがサポートされています (#30667)

ファイルリネーム時の挙動の改善

あるファイルを別ディレクトリへ移動した際のimportの書き換えが適切に動作するよう改善されています (#30628)

deno init

--npmオプション指定時の依存関係の取り扱いの変更

deno init --npmの実行時にカレントディレクトリではなく/tmp/deno_init_nm/<date>/<random>に作成した一時的なnode_modulesディレクトリを利用するよう挙動が変更されています (#30492)

その他のパッケージマネージャーも同様の実装をしているようで、それにあわせることなどが目的のようです。

Permissions

deno.jsonでのパーミッションの定義がサポート (--permission-set)

deno.jsonでパーミッションを定義する機能 (--permission-set)が実装されています。

deno.jsonpermissionsでパーミッションセットを定義できます:

{
  "permissions": {
    "default": {
      "net": true
    },
    "server": {
      "net": true,
      "read": ["data.txt"]
    }
  }
}

定義したパーミッションセットは--permission-setで適用することが可能です:

# (1) `permissions.default`を適用します
$ deno --permission-set main.js

# (2) `-P`は`--permission-set`の短縮形式です
$ deno -P main.js

# (3) `permissions.server`を適用します
$ deno --permission-set=server main.js

また、deno bench/deno compile/deno testの各コマンド向け専用のパーミッションセットを定義することも可能で、deno.jsonの対応するセクション配下のpermissionsで定義できます:

{
  "test": {
    "permissions": {
      "read": ["data.txt"]
    }
  }
}
# `test.permissions`を適用します
$ deno test --permission-set main.js

DENO_AUDIT_PERMISSIONS

DENO_AUDIT_PERMISSIONS環境変数がサポートされました (#30575)

この環境変数にパスを指定しておくと、jsonl形式でアプリケーションの実行中に要求されたパーミッションが記録されます:

# 1. アプリケーション実行時に`DENO_AUDIT_PERMISSIONS`にパスを指定しておきます
$ DENO_AUDIT_PERMISSIONS=permissions.jsonl deno run -A main.js

# 2. 指定されたパスに要求されたパーミッション情報が記録されます
$ jq 'pick(.permission, .value)' --compact-output permissions.jsonl
{"permission":"read","value":"README.md"}
{"permission":"write","value":"README.md"}
{"permission":"read","value":"Makefile"}
{"permission":"write","value":"Makefile"}

書き込まれるJSONのスキーマはcli/schemas/permission-audit.v1.jsonで定義されています。

また、DENO_TRACE_PERMISSIONS=1を設定しておくと、DENO_AUDIT_PERMISSIONSで指定されたパスの各レコードに追加でstackプロパティーが追加され、より詳細に情報が記録されます。


Deno API

Deno.ChildProcess.{stdout,stderr}へのResponseライクな問い合わせメソッドの追加

Deno.ChildProcess.stdoutDeno.ChildProcess.stderrに以下の4つのメソッドが追加されています:

  • arrayBuffer
  • bytes
  • json
  • text

Responseライクに子プロセスの出力内容を問い合わせることができます。

const command = new Deno.Command(Deno.execPath(), {
  args: ["json_reference"],
  stdout: "piped",
}).spawn();
const json = await command.stdout.json();

Deno.testへのbefore*/after*フックのサポート

以下の4つのAPIが追加されています:

  • Deno.test.beforeAll()
  • Deno.test.afterAll()
  • Deno.test.beforeEach()
  • Deno.test.afterEach()

VitestやJestなどと同様に、これらのAPIを利用することで該当モジュールにおける各テストケースの実行前後に特定の処理を実行することができます:

Deno.test.beforeEach(() => setup());
Deno.test.afterEach(() => teardown());
Deno.test("doSomethingAsync", async () => {
  await doSomethingAsync();
  // ...
});

tcpBacklogオプションの追加

Deno v2.4.5におけるTCPソケットのbacklogパラメータの変更に続けて、以下のAPIにtcpBacklogオプションが追加されています (#30541)

  • Deno.serve()
  • Deno.listen()
  • Deno.listenTls()

tcpBacklogオプションのデフォルト値は511です。

unsafelyDisableHostnameVerificationオプションの追加

Deno.connectTls()Deno.startTls()unsafelyDisableHostnameVerificationオプションが追加されています (#30409)

このオプションにtrueを設定すると、ホスト名の検証が無効化されます。

Deno.QuicListenerに関する破壊的変更

Deno.QuicListenerDeno.QuicConnではなくDeno.QuicIncomingyieldするように修正されています (#30150)

Web API

WebSocket

WebSocketheadersオプションが追加されています (#30321)

これはDeno独自のオプションのようで、WebSocket接続の確立時に送信されるHTTPヘッダーをカスタマイズできます。

fetch()

HTTPS_PROXYなどのプロキシー関連の環境変数でunix:vsock:形式のURLがサポートされています (#30377)

TypeScript 5.9

Deno内部のTypeScriptが5.8.3から5.9.2へアップデートされています (#30601)

これにあわせてTypedArrayに関連した型定義が更新されています (#30640, #30434, #30435)


V8 14.0.0

Deno内部のV8が14.0.0へアップデートされています (#30629)

これに伴い、廃止されたTemporal APIに関するDeno内部に存在していたパッチ処理が削除されています。Denoの公式ブログ記事によると、もうまもなく--unstable-temporalオプションを削除することが検討されているようです。

Node.js互換性の改善

--unstable-node-globalsの再導入

Deno v2.4で非推奨化されていた--unstable-node-globalsが再導入されています。今回のリリースでは、--unstable-node-globalsを指定した際にsetTimeoutsetIntervalnode:timersのものに置き換える機能が導入されています  (#29993)

bundleDependenciesのサポート

DenoがbundleDependencies (bundledDependencies) が定義されたnpmパケージを適切に取り扱うよう改善されています (#30521)

node:sqlite

DatabaseSyncSymbol.for("sqlite-type")プロパティーが定義されています (#30511)

Node.jsにはSQLite向けに様々なドライバーが存在しており、どのドライバーを使用しているのかを判断しやすくすることが目的のようです。bun:sqliteDatabaseにも同様のプロパティーを追加するPRが作成されているようです (oven-sh/bun#22109)

node:fs

WindowsにおいていくつかのAPIで必要以上にパーミッションが要求されていた問題が修正されています (#30535)

また、以下のAPIの互換性が改善されています:

  • symlink() - Windowsにおける互換性の改善 (#30555)
  • exists() - 不正なシンボリックリンクの取り扱いが改善 (#30507)
  • mkdtemp() - BufferUint8Array形式でのパスの指定がサポート (#30602)

node:http

Server#listensignalオプションがサポートされています (#30515)

また、ServerResponse#setHeadersが実装されています (#30586)

node:https

request()から返却されるClientRequestsocket.authorizedtrueに設定されるよう改善されています (#30641)

この改善によって、Yarn v1のaddコマンドが動作するようです。

node:tls

TLSSocketsocket引数においてnet.Socket以外のstream.Duplexの指定がサポートされています (#30465)

この改善によりmssqlパッケージにおいて接続時にエラーが発生する問題が修正されているようです。

node:child_process

deno init --npm@angular/createなどのモジュール内のJavaScriptファイルをサブプロセスとして実行するパッケージが動作するよう、spawn()などによってnode_modules内のスクリプトを実行する際にnpmパッケージに関する依存関係の解決情報 (DENO_DONT_USE_INTERNAL_NODE_COMPAT_STATE_FD) を引き継ぐように改善されています。(#30490)

また、fork()がNode.jsの--experimental-*オプションを無視するよう挙動が修正されています (#26351)

node:path

以下のAPIの互換性が改善されています:

node:crypto

hkdfSync()Uint8Array以外のTypedArrayが渡されると、間違った結果を返す問題が修正されています (#30463)

node:async_hooks

AsyncHookによるprocess.nextTick()の追跡がサポートされています (#30578)

Node-API

napi_create_external_buffer()finalize_cbNULLを渡せるよう改善されています (#30514)

参考