🦕

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

2021/09/16に公開

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

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

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

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

  1. Web Crypto API の追加
  2. deno lintdeno fmt に対するカスタマイズオプションの追加
  3. URLPattern の実装
  4. ネイティブ実装されたサーバーサイド WebSocket API の安定化
  5. ArrayBuffer がコピーなしでワーカー間を移動できるように
  6. ファイルをロックする API の追加
  7. OS シグナル API の変更
  8. fetch で相互 TLS がサポート
  9. DENO_AUTH_TOKENS でBASIC認証をサポート
  10. URLのパースが3倍速になった
  11. 子プロセスの user id および group id を指定することができるように
  12. std/http モジュールが高速化
  13. VSCode 拡張機能のアップデート
  14. TypeScript 4.4 にアップデート
  15. V8 9.4 にアップデート

1. Web Crypto API の追加

最近のリリースでは毎度のように Web Crypto API が拡充されていますが、今回のバージョンでも例にもれず API の追加実装がなされました。

  • crypto.subtle.exportKey():
    • HMAC キーが JWK および raw 形式でエクスポートできるようになった
    • RSA キーが PKCS #8 形式でエクスポートできるようになった
  • crypto.subtle.importKey():
    • HMAC キーが JWS および raw 形式でインポートできるようになった
    • RSA キーが PKCS #8 形式でインポートできるようになった
    • PBKDF2 キーが raw 形式でインポートできるようになった
  • crypto.subtle.generateKey():
    • RSA-OAEP, ECDH, AES キーの生成ができるようになった
  • crypto.subtle.deriveBits():
    • PBKDF2, HKDF の導出ができるようになった
  • crypto.subtle.verify():
    • ECDSA 署名の検証ができるようになった
  • crypto.subtle.encrypt():
    • RSA-OAEP アルゴリズムによる暗号化ができるようになった
  • crypto.subtle.decrypt():
    • RSA-OAEP アルゴリズムによる復号化ができるようになった

まだまだ Web Crypto API の追加作業は引き続き行われています。年内にはすべての API を実装する見込みです。興味のある方は Tracking issue を参照してください。

2. deno lintdeno fmt に対するカスタマイズオプションの追加

Deno はリンターとフォーマッタを内蔵していますが、これらはこれまでユーザーによる設定をすることができませんでした。つまり、リンターであれば、例えば特定のリントルールを無効化したり、逆にデフォルトでは無効になっているルールを有効化したり、といったことができませんでした。フォーマッタであれば、1行あたりの文字数や文末セミコロンの有無などを設定することができませんでした。

統一されたリンター・フォーマッタを適用することで、エコシステム全体としての利益になるという考えのもとこのようなデザインとなっていましたが、ユーザーから数多くの要望が寄せられたため、今回のバージョンからこれらのツールをユーザー側で設定できるような仕組みが追加されました。僕の認識では、特に deno fmt が提供するフォーマットルールに対する意見がかなり多かったように思います。1行の文字数が80と指定されていたのは度々議論を巻き起こしました。

ただし、依然としてこれらのツールはデフォルト設定のまま使うことが望ましいとされています。特段の理由がない限りはデフォルトで使うのが良いと思います。

設定の仕方をかんたんに紹介します。コマンドのオプションとして渡すやり方と、設定ファイルに記載するやり方があります。設定ファイルを使う場合、以下のような JSON ファイルを用意します。

{
  "compilerOptions": {
    "allowJs": true,
    "lib": ["deno.window"],
    "strict": true
  },
  "lint": {
    "files": {
      "include": ["src/"],
      "exclude": ["src/testdata/"]
    },
    "rules": {
      "tags": ["recommended"],
      "include": ["ban-untagged-todo"],
      "exclude": ["no-unused-vars"]
    }
  },
  "fmt": {
    "files": {
      "include": ["src/"],
      "exclude": ["src/testdata/"]
    },
    "options": {
      "useTabs": true,
      "lineWidth": 80,
      "indentWidth": 4,
      "singleQuote": true,
      "proseWrap": "preserve"
    }
  }
}

最初にある compilerOptions は、これまで deno run --config に渡して利用することのできた設定です。リンターおよびフォーマッタは、これまでの設定ファイルを拡張する形で設定を行います。設定の内容については直感的にわかると思うので、詳しくは省略します。files で対象とするファイル、対象外とするファイルを指定し、rules では有効にしたいリントルールと除外したいリントルールを指定します。options では lineWidth (1行あたりの行数) などを指定できます。

以上が設定ファイルを利用する場合の方法ですが、注意すべき点として、設定ファイルの自動検出機能は未実装であるということです。つまり、この設定ファイルを利用するためには、deno lint --config ./deno.json のように明示的に設定ファイルの場所を指定する必要があります。将来的に自動検出機能は実装される予定ですが、その際のファイル名は deno.json あるいは deno.jsonc となる予定なので、特にこだわりがなければこれらのファイル名にすることをおすすめします。

そして、コマンドラインオプションとして設定値を渡す方法ですが、上記の JSON ファイルのキーの名前がそのままオプション名となります。例えば deno lint に対しては --rules-include --rules-excludedeno fmt に対しては --options-line-width--options-indent-width のような感じです。

3. URLPattern の実装

URLPattern という新しい Web API があります。(W3C のドラフトはこちら) path-to-regex のような API となっています。具体例を見ていただくのがわかりやすいと思います:

const pattern = new URLPattern({ pathname: "/books/:id" });

console.log(pattern.test("https://example.com/books/123")); // true
console.log(pattern.test("https://example.com/books/123/456")); // false
console.log(pattern.test("https://example.com/books")); // false

console.log(pattern.exec("https://example.com/books/123")?.pathname);
// { input: "/books/123", groups: { id: "123" } } が得られる

これが Web API として提供されるのはかなり利便性が高そうですね!

1.14 時点では不安定機能のため、--unstable フラグが必要です。Chrome 95 にて安定化される予定で、それに合わせて Deno でも安定化される予定です。

4. ネイティブ実装されたサーバーサイド WebSocket API の安定化

1.12 にて ネイティブ HTTP サーバー実装による WebSocket API が導入されました。

この API は不安定機能とされていて、これまでは --unstable フラグが必要でした。しかし今回のバージョンから安定化され、--unstable なしで利用できるようになります。

5. ArrayBuffer がコピーなしでワーカー間を移動できるように

これまで、ArrayBuffer を別ワーカーに移動させたい場合は、コピーをする必要がありました。これはバッファのサイズが大きい場合かなりのオーバーヘッドとなってしまいます。
1.14 からは、コピーするのではなく、所有権を別ワーカーに移動させることができるようになりました。移動させたあと、元のワーカーではそのバッファを使うことができなくなります。

別ワーカーに ArrayBuffer を移動させるためには、postMessage() 関数の transfer オプションに移動させたいバッファを指定してください。

6. ファイルをロックする API の追加

ファイルに対する同期機構であるファイルロックですが、このファイルロックを行うための 4 つの API が追加されました。

  • Deno.flock
  • Deno.flockSync
  • Deno.funlock
  • Deno.funlockSync

不安定機能のため、--unstable フラグが必要です。

7. OS シグナル API の変更

Deno が提供している OS シグナル API に大きな改修が入りました。これまでシグナルの種類は Deno.Signal という enum で表現されていましたが、1.14 からは string の union として定義されました。つまり、SIGTERM をハンドリングするコードは、以下のように変わります。

// 1.14 よりも前のバージョン
for await (const _ of Deno.signal(Deno.Signal.SIGTERM)) {
  console.log("got SIGTERM!");
}

// 1.14 以降のバージョン
for await (const _ of Deno.signal("SIGTERM")) {
  console.log("got SIGTERM!");
}

また、いくつかのヘルパーメソッドを提供していた Deno.signals 名前空間が完全に削除されました。

シグナルに関する API の安定化がまもなくなされる予定です。

8. fetch で相互 TLS がサポート

fetch API にて、相互TLS (mutual TLS, mTLS とも) がサポートされました。クライアント側の証明書と秘密鍵を指定して Deno.createHttpClient を呼び出し、それを fetch に渡すことで利用可能になります。以下のような感じです。

const client = Deno.createHttpClient({
  certChain: Deno.readFileSync("./cert.pem"),
  privateKey: Deno.readFileSync("./key.pem"),
});
const resp = await fetch("https://example.com/", { client });

9. DENO_AUTH_TOKENS でBASIC認証をサポート

Deno 1.8 から DENO_AUTH_TOKENS 環境変数が使えるようになりました。 この環境変数に Bearer トークンを指定することで、認証が必要なサーバーからモジュールを取得することができます。

今回のバージョンから、この環境変数を使って、BASIC 認証も突破できるようになります。username:password@host の形式で指定します。以下のような感じです:

DENO_AUTH_TOKENS=a1b2c3d4e5f6@deno.land;testuser123:testpassabc@127.0.0.1:4554

このように指定すると、

  • deno.land には a1b2c3d4e5f6 という Bearer トークンを使ってアクセスする
  • 127.0.0.1:4554 には ユーザー名: testuser123 パスワード: testpassabc でアクセスする

というようになります。

10. URLのパースが3倍速になった

数週間前に「うそ、Deno の URL のパース、遅すぎ……?」という旨の報告がありました。これを受けて内部実装が調査・改善され、結果として v1.13 に比べて 3 倍のパフォーマンスとなりました。URL のパースは Web サーバーなどの用途で極めて多く行われる処理なため、この改善によるパフォーマンスへの効果は大きいと考えられています。

11. 子プロセスの user id および group id を指定することができるように

Deno で子プロセスを立ち上げる API として Deno.run() がありますが、この API で子プロセスの user id および group id を指定することができるようになりました。以下のように使います。

// uid (user id) を指定
Deno.run({
  cmd: [
    "echo",
    "Hello from root user",
  ],
  uid: 0,
});

// gid (group id) を指定
Deno.run({
  cmd: [
    "echo",
    "Hello from root group",
  ],
  gid: 0,
});

この機能は不安定機能のため、実行するには --unstable フラグが必要です。

12. std/http モジュールが高速化

Deno v1.13 にて HTTP サーバーのネイティブ実装が安定化 され、パフォーマンスが飛躍的に向上しました。これに伴って標準ライブラリの HTTP モジュール std/http はじきに削除される予定とされていましたが、Deno の標準ライブラリ v0.107.0 にて、ネイティブ実装 HTTP を利用するように標準ライブラリが改修されました。これで、std/http を利用する場合でもネイティブ実装による高速なパフォーマンスを得ることができるようになります。また、API も標準ライブラリ版のほうがよりユーザーフレンドリーな形になっています。

(🤔 std/http の削除はこれでなくなったのかな……)

13. VSCode 拡張機能のアップデート

VSCode 拡張機能 もアップデートされました。デバッグ設定の改善、コードレンズを利用する際の設定の改善、インストールサイズと起動時間の改善、設定ファイルとして deno.json deno.jsonc のサポート、など。

14. TypeScript 4.4 にアップデート

Deno に組み込まれている TypeScript のバージョンが 4.4 にあがりました。catch 句でキャッチされた値の型を unknown にすることができる --useUnknownInCatchVariables フラグなどが嬉しいアップデートです。TypeScript 4.4 自体の紹介は TypeScript 公式のリリース告知 をご覧ください。

15. V8 9.4 にアップデート

V8 のバージョンが 9.4 に上がりました。ユーザーに関係する一番大きな変更は、ES2022 の新しい言語機能である static initialization block がサポートされたことです。以下のようなコードを書くことができます。

class C {
  // このブロックは、class 自体が評価されるタイミングで一度だけ実行される
  static {
    console.log("Why is it always raining in Deno land?");
  }
}

おわり

以上、1.14.0 の紹介でした。
次のマイナーバージョン 1.15.0 のリリースは 2021 年 10 月 12 日の予定です。

なお、Deno 2.0 に向けての議論も始まっています。今のところ、11月に行われる予定(つまり 1.15 の次に 2.0 になる予定)ですが、大きな機能追加があるというよりは、破壊的な変更になってしまうため取り入れることができなかった機能がたまってきたので、その整理のためのメジャーバージョンアップとなる見込みです。詳しくは 2021年9月9日に行われたデザインミーティングの議事録 をご覧ください。

過去のリリース情報

1.13.0

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

1.12.0

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

1.11.0

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

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

Discussion