Denoばた会議 Monthly 第2回

Deno 2.0のリリースプラン

Deno 2.0のリリースプランが公開

他のissueとかを見る限り、2.0のリリースは12月以降になるかもしれません

Deno v1.15

新機能など

  • Node.js互換モード(--compat)
  • サブテスト
  • deno uninstallコマンド
  • FFI(Deno.dlopen)で非同期呼び出しやArrayBufferの受け取りがサポート
  • Deno.createHttpClientなどのAPIで複数のルート証明書の指定がサポート(caCertsオプション)
  • URLPattern, Deno.kill, Deno.Process.kill, Deno.resolveDnsの安定化

Node.js互換モード

Denoを実行する際に--compatオプションを指定すると、Node.jsの組み込みモジュールの読み込みが有効化されます。

import { EventEmitter } from "events";

const emitter = new EventEmitter();
  ...
emitter.emit("foo");
$ deno run --compat --unstable main.mjs

サブテスト

まだunstableですが、テストケースを入れ子にできるようになりました

Deno.test("nested test case", async (t) => {
  const success = await t.step("step 1", async (t) => {
    const success = await t.step("step 1-1", () => {
      throw new Error("Failed!");
    });
    if (!success) throw new Error("Failed!");

    await t.step("step 1-2", () => {});
  });

  if (success) throw new Error("Failed!");
});

deno uninstallコマンド

deno installでインストールしたコマンドをアンインストールできます。

$ deno uninstall udd

Deno.createHttpClientなどのAPIで複数のルート証明書の指定がサポート(caCertsオプション)

const caCert = await Deno.readTextFile("./my_ca_cert.pem");
const client = Deno.createHttpClient({
  caCerts: [caCert],
});
const res = await fetch("https://mydomain.com", { client });
console.log(await res.text());

deno_std v0.111.0

変更点

  • --compatオプションの実装に合わせてstd/nodedns, net, 及びhttpモジュールが追加
  • std/fsモジュールでexistsexistsSyncが非推奨化されました
  • std/hashが非推奨化されました (代わりにWeb Crypto APIとstd/cyrpotの使用を推奨)
  • std/ioのディレクトリ構造が大幅に変更

std/ioのディレクトリ構造が大幅に変更

  • std/io/bufio.tsが非推奨化されました (今後は代わりにstd/io/buffer.tsから読み込むのを推奨)
  • std/io/streams.tsが非推奨化されました (今後は代わりにstd/streamsから読み込むのを推奨)
  • std/io/ioutil.tsが非推奨化されました (今後は代わりにstd/io/util.tsから読み込むのを推奨)

std/ioのディレクトリ構造が大幅に変更

  • std/io/util.tsで公開されていたAPIがreadRangereadRangeSyncを除いてstd/io/streams.tsへ移動されました
    • 合わせて、iter及びiterSyncがそれぞれiterateReader及びiterateReaderSyncにリネームされています
  • std/io/util.tsreadRangereadRangeSyncstd/io/files.tsへ移動されました
  • std/io/ioutil.tsにあったcopyN/readShort/readInt/readLong/sliceLongToBytesstd/io/util.tsへ移動されました

Deno v1.14

新機能

  • deno fmtdeno lintで設定ファイルがサポート
  • URLPatternのサポート
  • Deno.upgradeWebSocket()が安定化
  • Deno.flock()などのファイルロックAPI (unstable)
  • Worker間でのArrayBufferのゼロコピー転送

など

deno fmtdeno lintで設定ファイルがサポート

{
  "fmt": {
    "files": {
      "include": ["main.ts"]
    }
  },
  "lint": {
    "rules": {
      "exclude": ["no-unused-vars"]
    }
  }
}

lint.deno.landがDeno Deployへ移行

deno_lintの公式サイトであるlint.deno.landがDeno Deployへ移行されました。

それに合わせて、内部実装がdext.ts+Tailwind CSSからFresh+Twindへ移行されています。

DenoやDeno Deployなどでフロントエンド開発を行う際に参考になるかもしれないため、興味のある方はソースコードも見てみるとよいかもしれません。

サードパーティモジュールの最新情報

deno-desktop

  • https://github.com/denosaurs/deno_desktop (Deno本体のフォークとして開発が進んでいるようです)
  • Scrapboxでhashrockさんが経緯などをまとめられています
  • 興味ある方はDenoのDiscordのdev-desktopチャンネルを見てみるとよいかもしれません

deno.ns

Denoネームスペースを提供するnpmパッケージ

import { Deno } from 'deno.ns';

console.log(Deno.version);

現在はdenolandオーガニゼーション配下で開発が行われています

Freshのアップデート

Freshとは

  • PreactベースのWebフレームワーク
  • Deno Deploy向けとありますが、CLIでも動きます
  • lint.deno.landで使われています

アップデート

  • APIの定義方法が大きく変更されました
  • <Suspense>を使用したストリーミングレンダリングのサポート
  • <Head>コンポーネントのサポート
  • /staticディレクトリに置いたファイルの静的な配信がサポートされました

APIの定義方法が大きく変更

今まではpages/api配下のファイルはAPIルートとして扱われていました。

今後は、APIを定義したいときは、以下のようにpagesディレクトリのファイルでhandler関数をexportする必要があります。

import { HandlerContext } from "https://raw.githubusercontent.com/lucacasonato/fresh/044da545134b91142e215dc349ec37a59e52cd25/server.ts";

export const handler = (_ctx: HandlerContext): Response => {
  return new Response("Hello, world!");
};

<Suspense>のサポート

/** @jsx h */
import { h, Suspense, useData } from "../deps.ts";

export default function Home() {
  return (
    <Suspense
      fallback={(
        <div>
          Loading...
        </div>
      )}
    >
      <SuspendedComponent />
    </Suspense>
  );
}

function SuspendedComponent() {
  const message = useData("/api/message", fetchMessage);
  return <div>{message}</div>;
}

async function fetchMessage(key: string): Promise<string> {
  const res = await fetch(key);
  return await res.text();
}

<Head>コンポーネントのサポート

/** @jsx h */
import { h, Head } from "../deps.ts";

export default function Home() {
  return (
    <div>
      <Head>
        <title>Hello</title>
      </Head>
      <h2>Home</h2>
    </div>
  );
}