虎の穴開発室ブログ

虎の穴ラボ株式会社所属のエンジニアが書く技術ブログです

MENU

Deno 1.31 へのアップデートと変更事項まとめ

皆さんこんにちは。おっくんです。

去る 2023 年 2 月 24 日に Deno 1.31 がリリースされました。 今回も、リリースノートを参考に 変更事項の気になるところを紹介します。

Deno 1.31

Deno 1.31 での変更事項をDeno 1.31 リリースノートを元に確認します。

package.json のサポートが追加されました

このリリースで package.json がサポートされ、 Node.js プロジェクトから Deno へ開発者がより簡単に移行することができるようになります。

package.json を Deno は自動的に検出して依存関係を解決します。 また、deno task を使って npm script が実行できるようにもなりました。

動作確認すると次の様になります。

$ node -v
v16.15.1

$ npm install express

# 次のソースコードを作成します。

$ cat index.mjs

import express from "express";
const app = express()

app.get('/', function (req, res) {
  res.send('Hello World')
})

app.listen(3000)

# この時点での package.json は次の通りです
$ cat .\package.json
{
  "dependencies": {
    "express": "^4.18.2"
  }
}

$ node index.mjs
# => サーバーが起動します。

# Deno での確認に移ります
$ deno -V
deno 1.31.1

$ deno run --allow-net --allow-read --allow-env .\index.mjs
error: Could not find npm package 'express' matching ^4.18.2. Try retrieving the latest npm package information by running with --reload

# リロードの要求が出たので、従います。
$ deno run --allow-net --allow-read --allow-env --reload .\index.mjs
# モジュールのダウンロードが始まります
# => サーバーが起動します。

# npm script が deno task から実行できます
# この時点での package.json は次の通りです
# scripts 以下を追記します
$ cat .\package.json
{
  "dependencies": {
    "express": "^4.18.2"
  },
  "scripts": {
    "fmt": "deno fmt" # <= 追記
  }
}

$ deno task fmt
Warning Currently only basic package.json `scripts` are supported. Programs like `rimraf` or `cross-env` will not work correctly. This will be fixed in the upcoming release.
Task fmt echo 'Do echo' && deno fmt
do echo
Checked 3 files

ポイントになるのは、これまで必要だった npm: が不要になり Node.js アプリケーションが、Deno でそのまま(モジュールの再読み込みは必要)実行できたことです。

「現在 Node.js で動かしているアプリケーションをそのまま Deno で動かせる」というこれまでに無かった互換性が提供されました。

deno task から npm script を実行もできましたが、これには注意事項もあります。 上記の動作確認で出ている警告の通り、 rimrafcross-env が使われるようなプログラムは現状正しく動作せず、将来の更新で修正される見込みになります。

併せて、Web 標準の import map のサポートも継続しており、Deno らしいスタイルでの開発も継続しています。

Node-API が安定化

このリリースで、Node-API が安定化になりました。 このことにより、Node-API に依存する npm パッケージの使用に --unstable が不要になります。 数多くのバグ修正が適用され、より多くの npm パッケージが使用できるようになっており、今後数週間で残りのバグにも対応する予定とのことです。

互換性レイヤーが、Deno 本体ランタイムに取り込まれました

これまで Node.js 互換レイヤーは、https://deno.land/std/node に標準ライブラリとして提供されており、必要な場合には1.5MB のダウンロードが行われていました。
このリリースにより、Node.js 互換レイヤーが Deno ランタイム本体に含まれるようになりました。
このことで起動時間の大幅短縮が見込まれるとともに、本体に取り込まれたことで API のポリフィルが容易になりにパフォーマンスの向上します。

Node.js 互換性レイヤーが提供するポリフィルを使用するには node:fs のようにインポートするということなので、試してみます。

# 読み込み対象ファイル
$ cat test.txt
Hello Deno!!

# node:fs を使用したファイル読み込み
$ cat .\test_node_fs.ts
import fs from "node:fs"

const file = fs.readFileSync("./test.txt")

console.log(new TextDecoder().decode(file))

# 実行
$ deno run --allow-read .\test_node_fs.ts
Hello Deno!!

node:fs を使用して動作していることが確認できます。

コマンドラインインターフェースの変更

deno bundle が非推奨になりました

deno bundle が非推奨になり、ヘルプ表示(deno -h)されなくなりました。 速やかな削除は予定されていませんが、deno compile deno_emit esbuild rollup などによるバンドルへの切り替えが推奨されています。

deno bench の出力形式として json が追加

deno bench --json を使用することで、deno bench の結果出力を json で得られるようになりました。

パーミッションの許可プロンプトが、改善されました

このリリースで、パーミッションの許可プロンプトは、これまでの y/n に加えて A を選択できるようになります。

環境変数へのアクセスを行うテストプログラムを例に確認します。

$ deno -V
deno 1.31.1

$ cat .\test_env.ts
Deno.env.get("KEY_A")
Deno.env.get("KEY_B")
Deno.env.get("KEY_C")

$ deno deno run .\test_env.ts
┌ ⚠️  Deno requests env access to "KEY_A".
├ Run again with --allow-env to bypass this prompt.
└ Allow? [y/n/A] (y = yes, allow; n = no, deny; A = allow all env permissions) > y

✅ Granted env access to "KEY_A".
┌ ⚠️  Deno requests env access to "KEY_B".
├ Run again with --allow-env to bypass this prompt.
└ Allow? [y/n/A] (y = yes, allow; n = no, deny; A = allow all env permissions) > y

✅ Granted env access to "KEY_A".
✅ Granted env access to "KEY_B".
┌ ⚠️  Deno requests env access to "KEY_C".
├ Run again with --allow-env to bypass this prompt.
└ Allow? [y/n/A] (y = yes, allow; n = no, deny; A = allow all env permissions) > y
# => 参照する環境変数1つ1つすべてにアクセス許可が求められました。

$ deno deno run .\test_env.ts
┌ ⚠️  Deno requests env access to "KEY_A".
├ Run again with --allow-env to bypass this prompt.
└ Allow? [y/n/A] (y = yes, allow; n = no, deny; A = allow all env permissions) > A

✅ Granted all env access.
# => 環境変数すべてのアクセスをまとめて許可できました。

内部的に多数の環境変数のアクセスがあるモジュールを使用するときなど、有効に使用できる機能だと思います。

deno compile が、分析可能な動的インポートで動作するようになりました

リリースノートにあるサンプルを Deno 1.30 とDeno 1.31 で比較します。

$ cat main.ts
const { add } = await import("./add.ts");

console.log(add(1, 2));

$ cat add.ts
export function add(a: number, b: number) {
  return a + b;
}

# Deno 1.30 の場合
$ deno 1.30.0

$ pwd
/usr/src/app/1_31

# Deno 1.30 でも動的インポートされたコードのコンパイルは動作する 
$ deno compile main.ts
Check file:///usr/src/app/1_31/main.ts
Compile file:///usr/src/app/1_31/main.ts
Emit 1_31

# コンパイル結果を実行するとエラーになる
$ ./1_31
error: Uncaught (in promise) TypeError: Module not found
const { add  } = await import("./add.ts");
                 ^
    at async file:///usr/src/app/1_31/main.ts:1:18

# Deno 1.31 の場合
$ deno -V
deno 1.31.0

$ deno compile main.ts
Check file:///usr/src/app/1_31/main.ts
Compile file:///usr/src/app/1_31/main.ts
Emit 1_31


# コンパイル結果が想定通り実行できる
$ ./1_31
3

Deno 1.31 は、動的インポートがコンパイル時に解決されて、実行可能ファイルにまとめられており、実行できました。

std ライブラリの変更

先の通り、std ライブラリに含まれていた互換性レイヤーがDeno ランタイム本体に取り込まれました。 これに併せて std ライブラリにあった https://deno.land/std/node が削除されています。

https://deno.land/std@0.178.0 から削除が行われているので、標準ライブラリの互換性レイヤーに依存している場合には、https://deno.land/std@0.177.0 に固定を行うか、node:fs を使用することが推奨されます。

その他

  • npm: 指定子は、リモートモジュールでもサポートされるようになりました
  • Deno API の変更
    • 次の2つのAPIが安定化し、実行時に --unstable を要求しなくなりました。
      • Deno.Command
      • Deno.osUptime()
  • API の機能拡張
    • Deno.build.os に寄り得られる結果が、より多くのOS種に対応しました
    • Deno.resolveDns() の実行中のキャンセルを目的として、signalを渡せるようになりました
  • deno fmt の引数に簡略化版が用意されました
    • 例: --options-line-width=100 に対応した簡略化版 --line-width=100
  • std/http/file_server.ts が Deno Deploy でより効率的に動作するようになりました
  • Deno に同梱されている V8 のバージョンが 11.0 に変わりました

まとめ

Deno 1.31 では、Node.js 互換性の中でも個別のパッケージ群や API への対応から「現在運用されている Node.js アプリケーションとその開発者」により踏み込んだものであると感じます。
このリリースで標準モジュールで公開されていた互換性レイヤーは Deno ランタイム本体に取り込まれており、取り込まれた API を Rust で書き換える issue が出ています。

https://github.com/denoland/deno/issues/17809

deno compile の動的インポートの動作については、しばらく前に試していた時に動作しないことを確認していたので、これが使えるようになるのはありがたいです。

次回のリリースも追いかけていきます。

P.S.

採用

虎の穴では一緒に働く仲間を募集中です!
この記事を読んで、興味を持っていただけた方はぜひ弊社の採用情報をご覧下さい。
yumenosora.co.jp