虎の穴開発室ブログ

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

MENU

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

皆さんこんにちは。 発売日に家電量販店に行きましたが、ガンダムエアリアルは入手できませんでした。おっくんです。

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

Deno 1.26

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

deno.com

Cache Web API のサポート

このリリースから Cache Web APIが、サポートされます。

developer.mozilla.org

このAPIにより、リクエストに基づくレスポンスのキャッシュができます。 API群の中から以下のものが実装されています。

  • CacheStorage::open()
  • CacheStorage::has()
  • CacheStorage::delete()
  • Cache::put()
  • Cache::match() ※一部
  • Cache::delete() ※一部

Cache Web APIには、add()や、keys() などは実装されていません。

また、ブラウザでの実装と比較すると、以下2点の差があります。

  • リクエストには、相対パスを使用できず、Request、URL のインスタンス、及び URL 文字列のみ受け付ける
  • Cache::match() と Cache::delete() の、クエリオプションがサポート外

最後にリリースノートにあるソースコードを参考に、以下のサンプルを作成しました。

[cache-web-api.ts]

import { serve } from "https://deno.land/std@0.158.0/http/server.ts";

const CACHE = await caches.open("v1");

let count = 0;

serve(async (req: Request) => {
  try {
    // 何かの外部リソースのアクセス失敗したケースを想定しますが
    // 今回は3回目のアクセスから失敗するということで代替します。
    if (count > 3) throw new Error();
    count++;

    const response = Response.json({ now: new Date() });
    await CACHE.put(req, response.clone());
    return response;
  } catch (e) {
    console.error(e);

    const res = await CACHE.match(req);
    if (res) {
      res.headers.set("x-cache-hit", "true");
      return res;
    }
  }
});

リソースアクセスに失敗した時(を想定した3回目のアクセスから失敗するという実装)、キャッシュの内容を返すという動きをします。 アクセスしてみると、3回目から時刻が更新されなくなっていることが確認できます。

--allow-sys パーミッションフラグが追加

新しいパーミッションフラグ --allow-sys が追加されました。

これまで、Deno.getUid()などのAPIを呼び出すためには、環境変数への参照を許可する --allow-env を与える必要がありました。

--allow-sys を使うことで、環境変数への参照を許可せずに済むようになります。

次のような、コードを用意します。

[access-sys.ts]

console.log(Deno.getUid());

Deno 1.25.0 とDeno 1.26.0 でそれぞれ動作させると次のようになります。

$ deno -V
deno 1.25.0

$ deno run --unstable --allow-env access-sys.ts.ts
0
# --allow-env で、Deno.getUid() にアクセスできます
$ deno -V
deno 1.26.0

$ deno run --unstable --allow-env access-sys.ts.ts
⚠️  ┌ Deno requests sys access to "getUid".
   ├ Requested by `Deno.getUid()` API
   ├ Run again with --allow-sys to bypass this prompt.
   └ Allow? [y/n] (y = yes, allow; n = no, deny) > y
# --allow-sys パーミッションを要求されます。

$ deno run --unstable --allow-sys access-sys.ts.ts
0

$ deno run --unstable --allow-sys=getUid access-sys.ts.ts
0 
# --allow-sys=getUid のように個別指定もできます。

--allow-sys フラグで制御できるAPI群は以下のものです。

  • Deno.hostname()
  • Deno.networkInterfaces()
  • Deno.loadavg()
  • Deno.getUid()
  • Deno.getGid()
  • Deno.osRelease()
  • Deno.systemMemoryInfo()

npm サポートが改善

--node-module-dir フラグが追加

node_modules ディレクトリが有ることを要求する一部の npm パッケージ向けに、node_modules にパッケージが保存される --node-module-dir フラグが追加されました。

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

[rainbow.ts]

import rainbow from 'npm:ansi-rainbow@1.0.1'
console.log(rainbow.r("Deno 1.26 is birth in 2022/09/29."))

こちらを --node-module-dir を付与して実行してみます。

$ pwd
/usr/src/app/deno1.26

$ tree
.
`-- rainbow.ts

0 directories, 3 files

$ deno run --unstable --node-modules-dir rainbow.ts
Deno 1.26 is birth in 2022/09/29.

# node_modules 以下が作成されている
$ tree
.
|-- node_modules
|   |-- ansi-rainbow -> /usr/src/app/deno1.26/node_modules/.deno/ansi-rainbow@1.0.1/node_modules/ansi-rainbow
|   `-- ansi-styles -> /usr/src/app/deno1.26/node_modules/.deno/ansi-styles@2.1.0/node_modules/ansi-styles
`-- rainbow.ts

$ ls -la node_modules/
total 0
drwxr-xr-x 1 root root 512 Oct  1 06:44 .
drwxrwxrwx 1 root root 512 Oct  1 06:44 ..
drwxr-xr-x 1 root root 512 Oct  1 06:44 .deno
lrwxrwxrwx 1 root root  85 Oct  1 06:44 ansi-rainbow -> /usr/src/app/deno1.26/node_modules/.deno/ansi-rainbow@1.0.1/node_modules/ansi-rainbow
lrwxrwxrwx 1 root root  83 Oct  1 06:44 ansi-styles -> /usr/src/app/deno1.26/node_modules/.deno/ansi-styles@2.1.0/node_modules/ansi-styles

前後のディレクトリ構成も比較しました。
単純に、node_modules が作成されるというだけでなく、シンボリックリンクも使われていました。 Node.js 環境の node_modules は、ディレクトリ階層にバージョン情報を持ちません。 Deno環境では、シンボリックリンクの先が、バージョン情報も抱えた構造になっています。

上記の操作の通り、npm install にあたる操作は不要で、実行時にモジュール群を取得します。

取得操作だけを先に行いたい場合には、deno cache を使うことができます。

たとえば、先のソースコードの扱っている ansi-rainbow のバージョンを古いものに切り替えてみます。

import rainbow from "npm:ansi-rainbow@1.0.0"; // 1.0.1 から変更
console.log(rainbow.r("Deno 1.26 is birth in 2022/09/29."));
tree
.
|-- node_modules
|   |-- ansi-rainbow -> /usr/src/app/deno1.26/node_modules/.deno/ansi-rainbow@1.0.1/node_modules/ansi-rainbow
|   `-- ansi-styles -> /usr/src/app/deno1.26/node_modules/.deno/ansi-styles@2.1.0/node_modules/ansi-styles
`-- rainbow.ts

# 関連モジュールをキャッシュ
$ deno cache --unstable --node-modules-dir rainbow.ts

# ansi-rainbow のシンボリック先が、ansi-rainbow@1.0.1/~~ からansi-rainbow@1.0.0/~~ に変更されています
$ tree
.
|-- node_modules
|   |-- ansi-rainbow -> /usr/src/app/deno1.26/node_modules/.deno/ansi-rainbow@1.0.0/node_modules/ansi-rainbow
|   `-- ansi-styles -> /usr/src/app/deno1.26/node_modules/.deno/ansi-styles@2.1.0/node_modules/ansi-styles
`-- rainbow.ts

(例示として、ansi-rainbow を取り扱いましたが、ansi-rainbow 自体は、--node-modules-dir が無くても動作します。)

--reload フラグの拡充 --reload=npm: --reload=npm:\ を追加

--reload フラグは、キャッシュ済みの外部リソースを再取得するためのフラグです。

このリリースで、npm モジュール群だけ再取得する --reload=npm:、特定のnpmモジュールだけ再取得する--reload=npm:\ 追加されました。

--compat モードが削除

deno 1.15 で登場した --compat モードは、削除されました。

ロードマップ

npm 指定子 (npm:<package>)の対応 のロードマップが公開されています。

github.com

今回の改善もこのロードマップの一環となっています。

Node.js 互換性 の向上

Deno 1.26 では、Node.js 互換性レイヤーにこれまでサポートしていなかったAPIの実装が含まれています。 また、互換性レイヤのテストターゲットがNode.js 16系から18系に変更になりました。 これは、Node.js 18系がLTSになることが理由になるようです。

今回リリースに含まれる、互換レイヤーに関わるものは以下の3点が挙げられています。

  • Streams のリファクタリング
  • child_process API群の導入
  • process.getuid() と process.getgid() の導入

パフォーマンスが向上

最近のリリースで顕著にパフォーマンスの向上が見られています。

詳細なグラフは、リリースノート本体を見ていただきたいのですが、以下の処理でのパフォーマンスが向上しています。

  • TextEncoder.encodeInto()
  • Deno.writeFile()
  • CSV パース処理
  • URL パース処理
  • ファイルシステム操作
  • Console.log()
  • TTY ops

WebCrypto が、Curve25519、Curve448 をサポート

Deno 1.26 では、WebCrypto API が、楕円曲線暗号の Curve25519 をサポートするようになりました。

また近日のリリースで、Curve448 のサポートが追加される予定です。

その他

  • API 安定化  - Deno.hostname() Deno.refTimer() Deno.unrefTimer() に --unstable フラグが不要に
  • Deno.setRaw(rid) が削除され、Deno.stdin.setRaw() が、unstable なAPIとしてリリース
  • Deno.serve() APIが改善
    Deno 1.27 で安定化を予定
  • モジュールダウンロードUI 外部モジュールの取得時に インタラクティブな「Download」のメッセージ表示されるようになりました。
  • Deno 1.26 には、TypeScript 4.8 が導入されています
    TypeScript 4.8 の詳細は、公式の発表で確認できます。

あとがき

Deno 1.26 では、--allow-sys と、npm 互換性の向上 が気になるものでした。

先の Deno 1.25のリリースノート追っかけ記事では、「動かないものが有ったので、報告してみたい」と書いていました。
実際報告をしてみたので、少し様子を見たいと思っています。
もしかすると、Deno向けの移植か、欲しい動作をするものをDeno ファーストで作ろうかと思っています。

リリースノートでは、Deno 1.26 自体の内容以外に デベロッパーエクスペリエンスの向上として、deno.land の検索機能の向上なども紹介されています。
こういった紹介の中で、deno.land/x に有る、サードパーティモジュールの表示の改善があり、実際の利用状況に基づいた星が付いたランキング付けがされるようになったことが紹介されています。

この星の付き方を見ると、利用者が Deno で何をしているのかの一端が垣間見えてきます。 例えば、上位に有るモジュールを見ると、lambda があります。

これは、AWS Lambda のハンドラー関数をDeno向けに記述するためのモジュールです。 ある程度の数のDenoの利用者は、実行環境としてLambdaを選んでいそうと読むこともできそうです。

他には、dotenvが上位に有るのですが、stdにdotenvが入ったのに、サードパーティ版を使い続けている方がまだまだいそうとも読めそうです。

それぞれの観点で発見も有るかと思います。ぜひ眺めてみてください。

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

P.S.

採用

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

LINE スタンプ

エンジニア専用のメイドちゃんスタンプが完成しました!
「あの場面」で思わず使いたくなるようなスタンプから、日常で役立つスタンプを合計 40 個用意しました。
エンジニアの皆さん、エンジニアでない方もぜひスタンプを確認してみてください。 store.line.me