皆さんこんにちは。おっくんです。
去る 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 を実行もできましたが、これには注意事項もあります。
上記の動作確認で出ている警告の通り、
rimraf
や cross-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()
- 次の2つのAPIが安定化し、実行時に --unstable を要求しなくなりました。
- 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