虎の穴開発室ブログ

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

MENU

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

皆さんこんにちは。
年始に届いたお届け物により、自宅のドンオニタイジンが座るようになりました。おっくんです。

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

Deno 1.30

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

ビルトイン Node.js モジュール のサポートを追加

Deno が、 npm: 指定子を使用してnpmパッケージを使用できるようになったことは記憶に新しいところです。 これらの npm パッケージは、Deno が持つ Node.js 互換性レイヤーを介して、 fs やpath process にアクセスできました。 今回のリリースから node: 指定子を使用して、これらのモジュールが Deno コードで使用できます。

リリースノートを参考に、以下のソースコードを用意します。

[node_comp.mjs]

import { readFileSync } from "node:fs";

console.log(readFileSync("read.txt", { encoding: "utf8" }));

実行すると次の様になります。

$ tree
.
|-- node_comp.mjs
`-- read.txt

$ cat read.txt
Deno !!

0 directories, 2 files
$ deno run --allow-read node_comp.mjs
Deno !!

Node.js 組み込みモジュールを呼び出しできました。 言語サーバーでもサポートされており、"fs" だけを記述した時には、クイックフィックスで "node:fs にする提案など表示されます。

Node.js で開発しているものを Deno に持ってくる場合には、モジュールをのインポートをしている箇所に node: をつけることで既存資産を生かすことができるでしょう。 node: 指定子は、Node.js 環境でも機能するため、node: をつけて運用することがリリースノートでも推奨されています。

数が膨大にあるなど、すべて書き足していくのが難しい場合には、import-map の使用が検討できるかと思いましたので、試してみました。

実行結果は、次の通りです。

$ tree
.
|-- import_map.json
|-- node_comp.mjs
`-- read.txt

0 directories, 3 files

$ cat node_comp.mjs
import { readFileSync } from "fs";

console.log(readFileSync("read.txt", { encoding: "utf8" }));

$ cat import_map.json
{

  "imports": {
    "fs": "node:fs"
  }
}

$ deno run --allow-read --import-map import_map.json node_comp.mjs
Deno !!

# Node.jsでも動作
$ node -v
v16.15.1

$ node node_comp.mjs
Deno !!

ソースコードで、node:fs を記述していた箇所は、fs に書き換えて、import-map に、fs: "node:fs" を記述することで、見た目は Node.js 向けのコードを Deno で動かすことも可能でした。

deno.json(c) に import-map を含められるようになりました。

これまで、deno.json(c) と import_map.json(c) は、別に管理をしてきました。 deno.json(c) は Deno により探索され、ある程度自動化されていましたが、import-map は、

  • --import-map import_map.json のような、引数で設定
  • deno.json(c) に "importMap": "./import_map.json" のように、ファイル指定

していました。

これらの方法に加えて、このリリースから、deno.json(c) に直接 import-map を記述できるようになりました。

先ほどの node: の例で挙げた import-map をdeno.jsonに埋め込むと次の様になります。

$ cat deno.jsonc
{
  "imports": {
    "fs": "node:fs"
  }
}
$ cat node_comp.mjs
import { readFileSync } from "fs";

console.log(readFileSync("read.txt", { encoding: "utf8" }));

# import-map の設定は指定していなくても deno.json(c) に書いた記述が効いているので動作する
$ deno run --allow-read node_comp.mjs 
Deno !!

Deno の動作を調整する近しい役割を持ちながらも個別にファイルを管理するのに手間を感じているなら、この利用方法に切り替えてしまうのが、良いと思います。

stable な API への変更

Deno.permissions に同期実行版が登場

Deno 1.8 で安定化した Deno.permissions API 群に、同期実行版が追加されます。 これまであったのが、Promise を返却する次の3つの API です。

  • Deno.permissions.query()
  • Deno.permissions.revoke()
  • Deno.permissions.request()

今回次の3つのAPIが追加されます。

  • Deno.permissions.querySync()
  • Deno.permissions.revokeSync()
  • Deno.permissions.requestSync()

引数はこれまでと同じで、直接結果を返します。

Deno.writeFile() と Deno.writeTextFile() が、ReadableStream を受け入れるようになりました

Deno.writeFile()、Deno.writeTextFile() が引数に、ReadableStream を設定できるようになっていますので、以下のサンプルで、確認します。

[write_readable_stream.ts]

const file = await Deno.open("read.txt")
const stream = file.readable

await Deno.writeFile("write.txt", stream)

実行すると次の通り動作します。

$ cat read.txt
Deno !!

$ deno run --allow-write --allow-read write_readable_stream.ts

$ cat write.txt
Deno !!

Deno.env.has(name) APIが追加されました

これまで環境変数を参照するとき、設定されているかどうかの判断は、実際に読んでみて検証し判断をしていました。
このリリースから、Deno.env.has(name) が追加されます。

テストコードで確認します。

[env_has.ts]

console.log(Deno.env.has("hoge"));
console.log(Deno.env.get("hoge"));

実行すると次の通り動作します。

# 環境変数hoge を設定なしで実行
$ deno run --allow-env env_has.ts
false
undefined

# 環境変数hoge を設定して実行
$ hoge=1 deno run --allow-env env_has.ts
true
1

Deno.Seeker APIが、オフセット値として、bigint を受け入れるようになります

リリースノートに書かれているコードを参考にして Deno 1.29 と動作を比較してみます。

const file = await Deno.open("./log.txt");
const cursor = await file.seek(150n, Deno.SeekMode.Start);
$ deno -V
deno 1.29.0
$ deno run -A seek.ts

$ deno -V
deno 1.30.0
$ deno run --allow-read seek.ts

特にエラーにならないようです。 ここで、型のチェックを行ってみると違いが見えてきます。

$ deno -V
deno 1.29.0
$ deno check seek.ts
Check file:///usr/src/app/1_30/seek.ts
error: TS2345 [ERROR]: Argument of type 'bigint' is not assignable to parameter of type 'number'.
const cursor = await file.seek(150n, Deno.SeekMode.Start);
                               ~~~~
    at file:///usr/src/app/1_30/seek.ts:2:32

$ deno -V
deno 1.30.0
$ deno check seek.ts

deno check では違いが出ました。
プルリクを見てみると、型としてbogintを受け入れるというのが、今回の修正の内容の様です。

github.com

もともとの、issue は2020年に立ったものでした。

github.com

今回の修正により、issue がクローズされており、1つの区切りが付いたようです。

その他

  • テストステップを関数にできるようになりました

API の安定化

次の2つのAPIが安定化し、--unstable フラグが不要になりました。

  • Deno.Listener.ref()
  • Deno.Listener.unref()

unstable な API への変更

Deno.Command({}).spawn() のデフォルト値変更

Deno.Command({}).spawn() のオプション stdin のデフォルト値が inherit に変更になります。

Deno.dlopen への変更

Deno.dlopen に構造体を値で渡すサポートが入ります。

新しい unstable な API の追加

次の3つのAPIが、追加されました。

  • Deno.osUptime()
  • Deno.Conn.ref()
  • Deno.Conn.unref()

Deno.osUptime() を動かしてみましょう。

[os_uptime.tss]

console.log(Deno.osUptime())

実行してみます。

$ deno run --unstable os_uptime.ts
⚠️  ┌ Deno requests sys access to "osUptime".
   ├ Requested by `Deno.osUptime()` API
   ├ Run again with --allow-sys to bypass this prompt.
   └ Allow? [y/n] (y = yes, allow; n = no, deny) > y
# 許可すると↑の表示は消える
✅ Granted sys access to "osUptime".
1769636

# 確認プロンプトを出さないためには、--allow-sys が必要

$ deno run --unstable --allow-sys os_uptime.ts
1769712

Deno.core 名前空間の削除

Deno.core 名前空間が削除され、この名前空間で公開されていたAPI群は非公開になりました。 Deno.core は、安定性の保証されないプライベートAPIだったためだそうです。 ほとんどのユーザーには影響しないということです。

deno fmt が、セミコロンの付与に関する構成をサポートするようになります

これまでも繰り返し要望されていたそうなのですが、セミコロンを使用しないスタイルで deno fmt によるフォーマットができるようになります。

セミコロンを使用しないスタイルで、フォーマットを行うには、 --options-no-semicolons をオプションとして渡すか、次のdeno.json(c) を用意します。

[deno.json(c)]

{
  "fmt": {
    "options": {
      "semiColons": false
    }
  }
}

その他

  • Node/npm の修正
    25件を超える npm 機能と Node-API のバグの修正
  • LSP(言語サーバー)の修正
    10件を超えるバグの修正

今回のリリースでは node: 指定子の導入により、より Node.js を普段使っている開発者が、Deno への切替えを行いやすい環境が整ったように感じます。 また、極個人的にはdeno.jsonにimport-mapを埋め込めるようになったのは、 非常に助かっています。 import-mapは deno init で作成されないファイルだったこともあり、面倒では無いもののちょっと手間でしたので。

1月に、2023年 第1四半期のロードマップが公開されています。

github.com

眺めてみると、Deno 1.30で既に導入されたものもあれば、現在も意見が交わされているものもあります。
Deno単体の利便性の観点では良いことに思えるが、ブラウザ互換性の観点で反対意見があったりと、なかなか考えさせられる内容にもなっています。

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

P.S.

採用

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