虎の穴開発室ブログ

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

MENU

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

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

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

Deno 1.29

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

npm 互換性の改善

カスタムレジストリを環境変数で設定できる

今回のリリースから、環境変数 NPM_CONFIG_REGISTRY が参照され、カスタム npm レジストリを設定できるようになりました。

現在は、すべての npm パッケージに影響しますが、将来的にはパッケージ毎に異なるレジストリが設定できるようになるそうです。

npm パッケージに対して deno install が使用できるように!

npm: 指定子を使ったnpm パッケージが deno install に対応しました。

リリースノートでは、cowsay@1.5.0 をインストールしています。

ここでは試しに、シンプルはHTTPサーバーである http-server を deno install し使ってみます。

www.npmjs.com

# http-server が要求するパーミッションを許可します
# ここで、許可しない場合実行時に確認されます
$ deno install --allow-net=0.0.0.0:8000 --allow-env --allow-read --allow-sys npm:http-server

# パッケージ名がそのままコマンドになります
$ http-server -p 8000
Starting up http-server, serving ./

# 出力内容を省略

Available on:
  http://127.0.0.1:8000
  http://192.168.16.6:8000
Hit CTRL-C to stop the server

ブラウザでアクセスすると http サーバーが起動していることが確認できます。

REPL の更新

REPL(対話的動作) にいくつかの変更が行われました。

npm をサポート

REPL で npm パッケージを使えるようになりました。
非 npm パッケージの導入同様に import するだけで使用できます。

$ deno
Deno 1.29.0
exit using ctrl+d, ctrl+c, or close()
REPL is running with all permissions allowed.
To specify permissions, run `deno repl` with allow flags.
> import chalk from "npm:chalk";
undefined
> console.log(chalk.red('Hello Deno!'));
Hello Deno!
undefined
>

deno repl がデフォルトでは、パーミッション無しになりました

これまで、deno repl ではすべてのパーミッションが許可された状態でしたが、このリリースより deno run 同様に確認が行われるようになります。

Deno 1.28 とも比較しながら確認します。

[Deno 1.28 での動作]

# パーミッションの確認が出ません
$ deno repl
Deno 1.28.0
exit using ctrl+d, ctrl+c, or close()
> Deno.networkInterfaces()
[
  {
    family: "IPv4",
    name: "lo",
    address: "127.0.0.1",
    netmask: "255.0.0.0",
    scopeid: null,
    cidr: "127.0.0.1/8",
    mac: "00:00:00:00:00:00"
  },
// 省略
]

[Deno 1.29 での動作]

# パーミッションの確認が出ます
$ deno repl
Deno 1.29.0
exit using ctrl+d, ctrl+c, or close()
> Deno.networkInterfaces()
✅ Granted sys access to "networkInterfaces".
[
  {
    family: "IPv4",
    name: "lo",
    address: "127.0.0.1",
    netmask: "255.0.0.0",
    scopeid: null,
    cidr: "127.0.0.1/8",
    mac: "00:00:00:00:00:00"
  },
// 省略
]

# --allow-sys を設定することで Deno.networkInterfaces() 実行時には、確認されなくなります
$ deno repl --allow-sys
Deno 1.29.0
exit using ctrl+d, ctrl+c, or close()
> Deno.networkInterfaces()
[
  {
    family: "IPv4",
    name: "lo",
    address: "127.0.0.1",
    netmask: "255.0.0.0",
    scopeid: null,
    cidr: "127.0.0.1/8",
    mac: "00:00:00:00:00:00"
  },
// 省略
]

この変更は、デフォルトで権限が付与されているというのは、Deno の「デフォルトで安全」であるというポリシーに反する状況であったために発生した変更だそうです。

Deno で対話的動作をするには denodeno repl の2つがありますが、deno はこれまで通りパーミッションがすべて許可されたものになります。 それを示す表示が入るようになりました。

$ deno
Deno 1.29.0
exit using ctrl+d, ctrl+c, or close()
REPL is running with all permissions allowed. <== パーミッションがすべてついていることを示す表示
To specify permissions, run `deno repl` with allow flags.

その他には、次の2つのリリースが有りました。

  • 実行ステートメント毎の履歴ファイルの更新が行われるようになったそうです。
  • --quiet フラグにより補助出力の抑制が優先されるようになりました。

QOL の向上

deno init

Deno 1.25 で登場した deno init は main.ts、main_test.ts の2つを作成するコマンドでした。
このリリースから、deno.jsonc、main_bench.ts も作成されるようになりました。 また、出力内容も更新されています。

構成ファイルの改善

このリリースから、構成ファイルで次の2つを制御できるようになります。

  • deno bench の対象と除外
  • ロックファイルの設定と無効化

IDEも、これらのオプションを提案するようになりました。

解決できないトップレベル await の表示が改善しました

トップレベル await を Deno はサポートしていますが、解決できない場合、エラーを出して終了していました。この表示が改善しました。 この機能は、V8 の新しいAPIに由来しているそうです。

Deno 1.28 と挙動を比較してみます。

次のソースを用意します。

[unresolve_promise.ts]

await new Promise((resolve) => {});
console.log("hello Deno!!");

Deno 1.28 と Deno 1.29 でそれぞれ実行してみます。

$ deno -V
deno 1.28.0

$ deno run unresolve_promise.ts
error: Module evaluation is still pending but there are no pending ops or dynamic imports. This situation is often caused by unresolved promises.
$ deno -V
deno 1.29.0

$ deno run unresolve_promise.ts
error: Top-level await promise never resolved
await new Promise((resolve) => {});
^
    at <anonymous> (file:///usr/src/app/1_29/unresolve_promise.ts:1:1)

Deno 1.28 のメッセージの表示だけであったものから、Deno 1.29 で対象箇所の特定が非常に容易になりました。

deno check のフラグに --all が追加されました

これまでは、次の様に deno check と deno run で、外部モジュールを含む型チェックをするコマンドのオプションが違っていました。

  • deno run --check=all main.ts
  • deno check --remote main.ts

このリリースから、deno check も all をオプションとして受け入れ、次の様に使用できます。

deno check --all main.ts

リリースノートでは、以前のコマンドも使用可能ではあるものの、新しいコマンドを推奨しています。
既に、deno check -h での表示されるオプションの一覧からは、--remote が削除されていました。
敢えて使う必要が無ければ切り替えたほうが良さそうです。

node_modules と.git ディレクトリを無視するように

deno fmt、deno lint の対象として node_modules と .git は無視されるようになりました。 もし対象にしたい場合は、次の様に明示的に設定が必要です。

$ deno fmt node_modules

その他には、次の3つのリリースが有りました。

  • 誤った --allow-* フラグの使用への警告が出るようになりました。
  • VSCode 向けにインレイヒントがデフォルトで有効になりました
  • --inspect-wait フラグの追加

Deno API の変更

安定化

これまで unstable だった以下のAPIが stable になりました。

  • Deno.TcpConn.setNoDelay()
  • Deno.TcpConn.setKeepAlive()

unstable な API の削除

次の3つのAPIが削除されました。

  • Deno.spawn()
  • Deno.spawnSync()
  • Deno.spawnChild()

これらの機能は Deno 1.28 で登場した Deno.Command が引き継ぎます。

Deno.Command#.spawn() の stdout と stderr はデフォルト値は、inherit になります

Deno 1.29 から Deno.Commnad の.spawn() コマンドの、stdout と stderr オプションのデフォルト値が inherit になりました。

リリースノートを参考に次のコードを用意し、Deno 1.28 と動作を比較します。

[spawn.ts]

await new Deno.Command("deno", {
  args: ["eval", "console.log(1); console.error(2); throw new Error;"],
}).spawn();
$ deno -V
deno 1.28.0

$ deno run --unstable --allow-run spown.ts
# 何も表示されません
$ deno -V
deno 1.29.0

$ deno run --unstable --allow-run spown.ts
1
2
error: Uncaught Error
console.log(1); console.error(2); throw new Error;
                                        ^
    at file:///usr/src/app/1_29/$deno$eval.js:1:41
# stdout と stderr は、Deno の stdout と stderr を継承しているので、Deno.Command で呼び出した結果が標準出力に載ってきます

Deno.Commnad の .output() と .outputSync() のstdout と stderr オプションのデフォルト値は引き続き piped です。

Deno.writeFile と Deno.writeTextFile にファイルを作成するオプション createNew が追加されました

以下の4つのファイルに書くAPIに、「新たにファイルを作成する」 createNew オプションが追加されます。

  • Deno.writeFile
  • Deno.writeFileSync
  • Deno.writeTextFile
  • Deno.writeTextFileSync

これまでも、create オプションは有りましたが、こちらは既にファイルが有る場合にエラーになりません。
createNew は既にファイルが有る場合にはエラーになります。

実際に確認すると、次の様になります。

$ cat sample.md
Sample

$ deno
Deno 1.29.0
exit using ctrl+d, ctrl+c, or close()
REPL is running with all permissions allowed.
To specify permissions, run `deno repl` with allow flags.
> await Deno.writeTextFile("sample.md", "update text", { create: true });
undefined
# create オプションでは、ファイルが既に有ってもエラーにならない

> await Deno.writeTextFile("sample.md", "update text 2", { createNew: true });
Uncaught AlreadyExists: File exists (os error 17), open 'sample.md'
    at async writeFile (deno:runtime/js/40_write_file.js:39:7)
    at async <anonymous>:2:1
# create オプションでは、ファイルが既に有るとエラーになる。

その他

  • Deno 1.29 には TypeScript 4.9 が導入されます
  • std モジュールの変更

まとめ

Deno 1.29 のリリースでは npm モジュールのインストールに対応するようになり、単純に npm との互換性とともに、Node.js を利用した開発への互換性が高まっていると感じます。

現在出ているプルリクで一つ注目しているものがあります。

github.com

パーミッション(特に例に出されているのは環境変数へのアクセス)について、まとめて許可できるオプションです。 今回 deno install の紹介で使用した http-server も該当するのですが、ある程度の規模のツールになると要求する環境変数も 多く、気持ちとして理解できるところがあります。
こちらが、Deno 1.30 のマイルストーンに入った後に、1.31 に延期になっていますが、期待しています。

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

P.S.

採用

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