🦕

Deno 1.11.0 がリリースされたので新機能や変更点の紹介

11 min read

deno illust
Copyright (c) 2018-2021 the Deno authors. MIT License.

日本時間の今日(2021 年 6 月 9 日)に Deno の v1.11.0 がリリースされました。

https://deno.com/blog/v1.11

詳細なリリース内容は上記のリリースノートにまとまっていますが、ざっと紹介していきたいと思います。

  1. 公式 Docker イメージ
  2. Web Crypto API の実装が進む
  3. fetch を中断することができるように
  4. deno lint が stable に
  5. deno compile で動的インポートの部分的な対応
  6. TextEncoderStreamTextDecoderStream がサポートされる
  7. BroadcastChannel が実験的サポート
  8. Deno LSP に様々な改良
  9. Deno 名前空間のいくつかの API の引数が変更
  10. TypeScript 4.3
  11. Web Platform Tests の対応状況を可視化

1. 公式 Docker イメージ

これまでDenoはコミュニティによって管理されているDockerイメージしかありませんでしたが、ついに公式によるDockerイメージ提供が始まりました。

https://hub.docker.com/r/denoland/deno
  • Alpine Linux
  • CentOS
  • Debian (default)
  • Distroless
  • Ubuntu
REPLを起動
$ docker run -it --init denoland/deno:1.11.0 repl
コンテナの中に入る
$ docker run -it --init --entrypoint sh denoland/deno:1.11.0
main.ts を実行
# 1. 1993番ポートをバインド
# 2. カレントワーキングディレクトリをコンテナ内の `/app` にマウント
# した上で、`--allow-run /app/main.ts` を起動
$ docker run -it --init -p 1993:1993 -v $PWD:/app denoland/deno:1.11.0 run --allow-net /app/main.ts

2. Web Crypto API の実装が進む

Web Crypto API への対応が進みました。Deno は 1.0 から crypto.getRandomValus() をサポートしていましたが、今回のリリースではさらにハッシュ化および UUID 生成の API が追加されました。

以下のように、SubtleCrypto.digest API によって sha-256、sha-384、sha-512、sha-1 のハッシュ化を行うことができます。

import { encodeToString } from "https://deno.land/std@0.97.0/encoding/hex.ts";
const data = new TextEncoder().encode("Deno 1.11 has been released!");
const digest = await crypto.subtle.digest("sha-256", data.buffer);
console.log("Digest:", encodeToString(new Uint8Array(digest)));

また、以下のように crypto.randomUUID() API を使うことで、RFC 4122 に準拠した UUID v4 を生成することができるようにもなりました。

console.log("Random UUID:", crypto.randomUUID());

来月リリース予定の Deno 1.12 に向けて Web Crypto API の実装がさらに進んでいく予定です。

3. fetch を中断することができるようになった

例えば数秒待ってもレスポンスが返ってこないときなど、fetch の実行を中断させたいときがあります。そのようなときに使える API として AbortSignal が追加されました(例のごとく、Web 標準の API です)。

// まず `AbortController` インスタンスを生成する
// のちほど `fetch` を中断すべきタイミングで `AbortSignal` を発行する役割
const controller = new AbortController();
// `fetch` のタイムアウトを5秒後に設定する
// 実際のアプリでは、タイムアウトより前に処理が完了したら、タイムアウトを解除するなどする
setTimeout(() => controller.abort(), 5000);

// ある URL に対して `fetch` を実行し、そのときに `AbortController` から生成した `signal` を渡す
// リクエストの送信中、あるいはレスポンスヘッダの受信中にシグナルが発火したら、`fetch` は Reject となる
const response = await fetch("https://myslowapi.com/users", {
  signal: controller.signal,
});
// レスポンスをパースする
// ここで、シグナルが発火するよりも前にこのパース処理も完了しなければならない、ということに注意
const users = await response.json();

リクエストはいかなるタイミングでも中断することができます。つまり、リクエストヘッダ送信中、リクエストボディ送信中、レスポンスヘッダ受信中、レスポンスボディ受信中、のいずれのタイミングでも中断することができるということです。

4. deno lint が stable に

2020 年 6 月にリリースされた Deno 1.1.0 で導入された Deno の組み込みリンター deno lint ですが、これまでは「不安定」機能として提供されていました。まだ開発初期段階であり、様々なバグを含んでいる可能性があるということをユーザーに知らせるためです。

1 年経ち、コミュニティからの多数のフィードバックを受けてある程度安定的な機能を提供できるようになったことから、ついに "stable" に昇格しました。

"stable" とはいえ、今後も必要に応じて lint ルールの追加や削除は行われる予定です。

5. deno compile で動的インポートの部分的な対応

v1.6.0 で追加された単一の実行バイナリを生成する deno compile コマンドですが、さまざまな機能的制約を含んでいます。制約のうち特に改善が求められていたのが、動的インポートのサポートです。そこで今回のリリースでは、Data URI による動的インポートへのサポートが追加されました。これにより、ローカル・リモート問わずソースファイルを読み込むことができるようになります。

例を見てみましょう。以下のように読み込み対象のソースコードとして some_source_code.js を作成します。

some_source_code.js
export const hello = "Hello Deno!";

このファイルを、以下のようにして動的インポートすることができます。

const sourceCode = await Deno.readTextFile("./some_source_code.js");
const dataUrl = "data:text/javascript;base64," + btoa(sourceCode);
const c = await import(dataUrl);
console.log(c.hello); // "Hello Deno!" が出力される

なお、例のように、一度 Data URI に変換しなければならないということに注意してください。直接ファイルシステム上あるいはネットワーク越しにインポートをすることは、現状では不可能です。

また、もう 1 つ deno compile への要望として、ランタイムで利用できるコンパイラ API である Deno.emit() を使いたい、というものがありました。今回のバージョンからこの API も deno compile の生成バイナリ内で利用できるようになりました。

6. TextEncoderStreamTextDecoderStream がサポートされる

2 つのモダンな Web API TextEncoderStreamTextDecoderStream が実装されました。ReadableStream とともに使うことで、簡単にバイト列を文字列に、あるいは文字列をバイト列に変換することができます。

以下の例では、fetch のレスポンスボディストリームを TextDecoderStream にパイプしています。これによってバイト列ストリームから文字列セグメントへと変換されます。

const response = await fetch("https://http2.golang.org/clockstream");
const body = response.body.pipeThrough(new TextDecoderStream());
for await (const chunk of body) {
  console.log("!!chunk start!!", chunk, "!!chunk end!!");
}

7. BroadcastChannel が実験的サポート

--unstable フラグの下で BroadcastChannel のプロトタイプが利用できます。BroadcastChannel を使うことで、複雑な JavaScript オブジェクトからなるメッセージを、ワーカー間で配信することができます。現在は同一プロセス内のワーカーに制限されていますが、将来的には、別プロセスのワーカー間でも、オリジン[1]が同じなのであれば配信を行うことができるようになる予定です。

以下の例は、ワーカーを 3 つ立ち上げて、それらにメッセージを送っています。

const c = new BroadcastChannel("foo");
const url = new URL("./worker.js", import.meta.url).href;

for (let i = 0; i < 3; i++) {
  const w = new Worker(url, { type: "module" });
  await new Promise((resolve) => w.onmessage = resolve); // ワーカーの準備ができるまで待つ
}

c.postMessage({ hello: [1, 2, 3] });
worker.js
const c = new BroadcastChannel("foo");
self.postMessage("ready");
c.onmessage = (e) => {
  console.log("got message", e.data);
};

8. Deno LSP に様々な改良

Deno の内蔵 LSP にも多くの機能追加がされました。1 つずつ紹介します。

個々のテストケースを実行できる

Test code lens
https://deno.com/blog/v1.11 より

Deno.test で書いたテストケースの上に Run Test が出現するようになり、これをクリックすることでテストケースを個別実行することができるようになりました。
VSCode でこの機能を利用するためには Deno 拡張 の v3.6.0 以降が必要です。

リソース単位の設定をサポート

Language Server Protocol の一部として、リソース単位の設定ができるようになりました。これは VSCode においては、マルチルートワークスペースで異なるフォルダに対して特定の設定を行うことができる、ということになります。詳しくは ワークスペースフォルダに関するドキュメント を参照してください。

レジストリの自動検出

Deno 1.10 から、import を書くときの自動補完機能が追加されています。しかし、1.10 では、補完対象とするレジストリを手動で設定に追記しなければなりませんでした。
今回のバージョンからは、import 補完機能に対応しているレジストリから import しようとしていることを検知すると、以下のようにプロンプトが出現するようになります。これによって、手動で設定ファイルを編集する必要がなくなります。

registry auto completion prompt
https://deno.com/blog/v1.11 より

JSON(C) および Markdown のフォーマットをサポート

これまで JavaScript、JSX、TypeScript、TSX のフォーマットには対応していましたが、今回のバージョンから JSON、JSONC、Markdown のフォーマットも行えるようになりました。

vscode config for default formatter
https://deno.com/blog/v1.11 より

X-Deno-Warning の内容を表示

Deno のモジュールを配信するサーバーは、X-Deno-Warning ヘッダを付けることで、何らかの警告情報をクライアント側に知らせることができます。例えば、deno.land/x は、以下のようにバージョンを指定しないインポートをしようとしたとき、X-Deno-Warning ヘッダに警告メッセージをセットします。

import { Application } from "https://deno.land/x/oak/mod.ts";

今回のバージョンから、このヘッダにセットされた警告メッセージを、LSPが表示してくれるようになりました。

lsp shows diagnostic message
https://deno.com/blog/v1.11 より

deno lint のヒントを表示

deno lint は、何らかの問題を検出した際、メッセージとともに、どのようにすれば問題を直すことができるのかを示す「ヒント」を提供しています。しかし、Deno LSP はこれまで、この「ヒント」を表示していませんでした。

only message from the linter is shown in 1.10
v1.10 での表示 https://deno.com/blog/v1.11 より

今回のバージョンからは、以下のようにヒントを合わせて表示するようになりました。

hint is shown as well in 1.11
v1.11 での表示 https://deno.com/blog/v1.11 より

@deno-types と triple-slash reference に対応した診断結果を表示

// @deno-types および /// <reference /> (triple-slash directives) を解釈できるようになり、これらのコメントに対する診断結果を表示するようになりました。

9. Deno 名前空間のいくつかの API の引数が変更

以下の 9 API の引数に修正が入りました。

これらの API は、引数にファイルパスを表す string を受け取るのですが、今回の修正で URL 型も受け取れるようになりました。ただし、file:// から始まる URL のみ正しく動作します。

既存の string 型の引数も依然として問題なく動くため、後方互換性は保たれています。

10. TypeScript 4.3

内蔵されている TypeScript のバージョンが 4.3.2 になりました。

11. Web Platform Tests の対応状況を可視化

Deno は Web 標準への準拠を目指していて、ブラウザ上で動く API との互換性を高めるため多くのコントリビュータが貢献しています。
Web API との互換性を高めるための指標として役立つのが、Web Platform Tests (WPT) です。Chrome、Firefox、Safari などのブラウザがこのテストスイートを共有することで、Web API のブラウザ間での互換性が担保されています。
Deno も WPT を実行しており、現在どれくらいのテストが通っているのかを確認できるダッシュボードが公開されました。

https://wpt.deno.land/

主要ブラウザのテスト結果がまとめられている https://wpt.fyi/ に Deno を追加する作業が進行中とのことです。また、どの Web API が Deno で利用可能なのかを MDN にも掲載する作業も進行中のようです。

おわり

以上、1.11.0 の紹介でした。
次のマイナーバージョン 1.12.0 のリリースは 2021 年 7 月 13 日の予定です。

過去のリリース情報

1.10.1

https://zenn.dev/magurotuna/articles/deno-release-note-1-10-1
1.9.0

https://zenn.dev/magurotuna/articles/deno-release-note-1-9-0
1.8.0

https://zenn.dev/magurotuna/articles/deno-release-note-1-8-0
1.7.0

https://zenn.dev/magurotuna/articles/55575eb16ae422
1.6.0

https://zenn.dev/magurotuna/articles/020f6b103937ed
脚注
  1. オリジンとは、URL のうちプロトコル、ホスト名、ポート番号の部分のことです。Deno においては起動時のオプション --location で指定可能です。 ↩︎

Discussion

ログインするとコメントできます