Denoばた会議 Monthly 第8回

Deno v1.21

deno checkコマンド

指定されたモジュールの型チェックを行うコマンド

$ deno check mod.ts

このコマンドの追加により、deno runコマンドでのデフォルトの型チェックは将来的に無効化される予定です。

新しいサブプロセスAPI

Deno名前空間にspawn, spawnChild, 及びspawnSyncの3つのAPIが追加

高レベルAPI

const { stdout, status } = await Deno.spawn("echo", {
  args: ["foo"],
});
console.assert("foo\n" === new TextDecoder().decode(stdout));
console.assert(status.success);

低レベルAPI

const child = Deno.spawnChild("deno", {
  args: ["--version"],
});
for await (const output of child.stdout.pipeThrough(new TextDecoderStream())) {
  console.log(output);
}
const child = Deno.spawnChild("gh", {
  args: ["issue", "list"],
});
const { stdout, status } = await child.output();
console.assert(status.success);
console.log(new TextDecoder().decode(stdout));

deno lspの改善

  • deno.json(c)で定義されたタスクの実行をサポート
    • vscode-denoを入れておけば、Tasks: Run Taskでタスクを実行できます
  • ワークスペース内の特定ディレクトリでのみLSPを有効化できるようになりました ("enablePaths"オプション)
  • vscodeのTesting APIがサポート
    • Testing: Focus on Test Explorer Viewコマンドを実行すると、テストケースの一覧を表示できます

deno testの改善

TestContextオブジェクトにテストケースに関するメタデータが追加 (name, origin, 及びparentプロパティ)

Deno.test("math", async (t) => {
  assert(t.name === "math");
  assert(t.origin === Deno.mainModule);
  await t.step("sum", (t) => {
    assert(t.parent.name === "math");
    assert(t.name === "sum");
    assert(6 === sum(1, 2, 3));
  });
});

テストレポートの改善

Deno.test("foo", () => {
  console.log({ message: "foo" });
  console.log("baz");
});

console.log()で出力された内容がテストランナーによって補足されます:

running 1 test from ./sample_test.js
foo ...
------- output -------
{ message: "foo" }
baz
----- output end -----

deno fmtdeno lintの大幅な高速化

deno fmtdeno lintでインクリメンタルキャッシュがサポートされました。

これらのコマンドの実行結果をキャッシュすることで、大幅な高速化が見込まれるようです。

deno benchの改善

nオプションとwarmupオプションが削除されています。

Deno.bench("URLPattern", () => {
  const pattern = new URLPattern({ pathname: "/users/:id" });
  pattern.test("http://locahost:3000/users/123");
});

今後は、Deno本体が信頼のある結果を得られるまで繰り返しベンチマークを実行してくれます。

ベンチマークのグルーピング

Deno.bench({ name: "add", group: "math", baseline: true, fn: () => add(1, 2) });
Deno.bench({ name: "sum", group: "math", fn: () => sum(1, 2, 3, 4, 5) });

レポート:

benchmark      time (avg)             (min … max)       p75       p99      p995
------------------------------------------------- -----------------------------
add        169.17 ns/iter    (157.29 ns … 249 ns) 169.19 ns 221.56 ns 246.76 ns
sum        192.72 ns/iter (187.26 ns … 255.52 ns) 193.52 ns  228.4 ns 230.39 ns
summary
  add
   1.14x times faster than sum

reportError()のサポート

Uncaught exceptionを明示的に発生させることができます。

addEventListener("error", e => {
  console.error(e.error);
  e.preventDefault(); // これを呼ばないとexit code=1で終了する
});
reportError(new Error("foo"));

deno replの改善

--eval-fileオプションが追加され、REPLの起動前に読み込みたいファイルを指定できるようになりました。

$ deno repl --eval-file=sum.js
Deno 1.21.0
exit using ctrl+d or close()
> sum(1, 2, 3)
6

その他にも、clear()関数がサポートされています。(挙動はconsole.clear()と同等)

Deno.Listenerrefunrefメソッドが追加 (unstable)

unref()が呼ばれたListenerはプロセスの終了をブロックしなくなります (タイマにDeno.unrefTimerを呼んだときと同様の挙動をします)

deno_std/node/netでのServer.ref()Server.unref()の実装で利用されています。

DENO_NO_PROMPT環境変数のサポート

この環境変数を設定すると、Deno v1.19で有効化されたプロンプトの挙動を無効化できるようになりました。(--no-promptを指定したときと同様の挙動です)

$ DENO_NO_PROMPT=1 deno run main.ts

deno_stdのアップデート

testing/mock

import { assertSpyCall, assertSpyCalls, spy } from "https://deno.land/std@0.136.0/testing/mock.ts";

const add = (a, b) => a + b;
const addSpy = spy(add);

assertEquals(addSpy(1, 2), 3); // => OK
assertEquals(addSpy(2, 3), 5); // => OK
assertSpyCall(addSpy, 0, {
  args: [1, 2],
  returned: 3,
}); // => OK
assertSpyCall(addSpy, 1, {
  args: [2, 3],
  returned: 5,
}); // => OK

assertSpyCalls(addSpy, 2); // => OK

testing/bdd

import { assertEquals } from "https://deno.land/std@0.136.0/testing/asserts.ts";
import { describe, it } from "https://deno.land/std@0.136.0/testing/bdd.ts";

describe("sum", () => {
  it("should return sum of numbers", () => {
    assertEquals(sum(1, 2, 5), 8)
  });

  it("should return 0 when no arguments are given", () => {
    assertEquals(sum(), 0);
  });
});

定義したテストケースはdeno testで実行できます。

testing/time

import { afterEach, beforeEach, describe, it } from "https://deno.land/std@0.136.0/testing/bdd.ts"
import { assertSpyCalls, spy } from "https://deno.land/std@0.136.0/testing/mock.ts";
import { FakeTime } from "https://deno.land/std@0.136.0/testing/time.ts";

describe("FakeTime", () => {
  let fakeTime;
  beforeEach(() => {
    fakeTime = new FakeTime("2022-04-01T00:00:00.000Z");
  });
  afterEach(() => fakeTime.restore());

  it("replaces Date with fake implementation", () => {
    assertEquals("2022-04-01T00:00:00.000Z", new Date().toISOString());
  });

  it("replaces setInterval with fake implementation", () => {
    const cb = spy();
    const intervalID = setInterval(cb, 2000);
    fakeTime.tick(7000);
    try {
      assertSpyCalls(cb, 3);
    } finally {
      clearInterval(intervalID);
    }
  });
});

testing/snapshot

import { assertSnapshot } from "https://deno.land/std@0.136.0/testing/snapshot.ts"

Deno.test("doSomething", async (t) => {
  const result = doSomething();
  await assertSnapshot(t, result);
});

スナップショットの更新:

# スナップショットは__snapshots__に書き込まれます
$ deno test --allow-read --allow-write tests/some_test.js -- --update

Supabase Functions

SupabaseでSupabase FunctionsというFaaSが利用できるようになりました。

Supabase FunctionsはDeno Deployをベースにしており、TypeScriptなどを利用してコードを記述できます。

Netlify Edge Functions (public beta)

NetlifyのEdgeネットワーク上でJavaScriptやTypeScript関数を実行することができます

現在、RemixAstro, Nuxt3など様々なフレームワークでNetlify Edge Functionsのサポートが提供されています

Aleph.js v1 alpha

  • Deno Deployのサポート
  • Remixライクなデータ読み込みAPI
  • React以外のフレームワークのサポート (Vue.js)
  • UnoCSSの組み込みサポート
  • ts/jsx/tsxのオンデマンドでの変換

Ultra v0.8.0

  • React v18のサポート
  • APIルートのサポート (src/api/**.{ts,js})
  • deno.jsonとの統合
  • サードパーティモジュールのベンダリング
  • Oakとの互換性

など、様々な変更が実施されています。

stripe-nodeパッケージでのDenoサポートについて

stripe-nodeパッケージがDenoでも動作するようになったようです。

aiotterさんに情報提供いただきました🙏🙏