虎の穴開発室ブログ

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

MENU

Deno Deploy を触ってみよう ~ アプリケーションの作成と更新 ~

皆さんこんにちは、積みを重ねています。おっくんです。

Deno の アプリケーションをホスティングしてくれる Deno Deploy が、2021 年 03 月 29 日に公開されました。 毎度 Deno のリリース内容を追いかけている本ブログでも Deno Deploy を試してみたいと思います。

その前に...

2021 年 03 月 29 日 に Deno Deploy の公開と同じタイミングで、Deno が会社に変わりました。

Announcing the Deno Company

deno.com

この中でポイントになるのが、以下の 2 点だと思います。

  • Deno のライセンスは、MIT を維持する
  • 商用アプリケーションを構築できるインフラを提供する

ライセンスに変更が無いので、今後も存分に Deno を使えることがありがたい限りです。 そして商用サービス構築の入口が、今回の Deno Deploy になるようです。

Pricing & Limitsを見ると Deno Deploy のパブリックベータ期間が終了すると詳細な価格が示されるとしています。

deno.com

Deno Deploy で動くアプリケーションを作ってみる

まずはローカルで

最終的には、Deno Deploy にデプロイしますが、まずはローカルで動作確認してみます。 次のコマンドで、deployctl をインストールできます。

deno install --allow-read --allow-write --allow-env --allow-net --allow-run --no-check -f https://deno.land/x/deploy/deployctl.ts

deployctl の実行は、Deno 1.9.1 が必須なので、1.9.0 以前のバージョンを使用している場合には、deno upgrade しましょう

error: The Deno version you are using is too old. Please update to Deno 1.9.1 or later. To do this run `deno upgrade`.

コマンドを確認します。

$ deployctl -h
deployctl 0.3.0
Run Deno Deploy scripts locally.

To run a script locally:
  deployctl run https://deno.land/x/deploy/examples/hello.js

To run a script locally and watch changes:
  deployctl run --watch https://deno.land/x/deploy/examples/hello.js

SUBCOMMANDS:
    run       Run a script given a filename or url
    check     Perform type checking of the script without actually running it
    types     Print the Deno Deploy TypeScript declarations
    upgrade   Upgrade deployctl to the given version (defaults to latest)

例に倣って実行してみます。

$ deployctl run https://deno.land/x/deploy/examples/hello.js
Check file:///Users/developer/dev/deno3/$deno$eval.ts
Check data:application/typescript;base64,aW1wb3J0IHR5cGUge30gZnJvbSAiZmlsZTovLy9Vc2Vycy9kZXZlbG9wZXIvTGlicmFyeS9DYWNoZXMvZGVuby9odHRwcy9kZW5vLmxhbmQvMzg5NzYyNTc4ZGYyYThhZTBhNmQxODk1ZDUxYWYxNWNjZDE3MWI4MTIxM2NiZWY0NDg0YzQxNDUyMmZjMTQyZi50cyI7aW1wb3J0IHR5cGUge30gZnJvbSAiZmlsZTovLy9Vc2Vycy9kZXZlbG9wZXIvTGlicmFyeS9DYWNoZXMvZGVuby9odHRwcy9kZW5vLmxhbmQvYTU0ODczY2U3NDU0OTE5NDJhYmRlODg3NGI1ZWE5MmYzNDNhOWJlNGE1NDEzZTc4ZGZlN2M5NGZjZmUyYjIwMS50cyI7aW1wb3J0IHR5cGUge30gZnJvbSAiZmlsZTovLy9Vc2Vycy9kZXZlbG9wZXIvTGlicmFyeS9DYWNoZXMvZGVuby9odHRwcy9kZW5vLmxhbmQvNzQ2N2JjNzY2Mzg4MGI1MzM5ZjM2ZWUwYWQ2ZGNiY2QzNDljMmI5YzM5NmE0OGI0MDYxNjc5YzNiZWNkMTNiMi50cyI7aW1wb3J0ICJodHRwczovL2Rlbm8ubGFuZC94L2RlcGxveS9leGFtcGxlcy9oZWxsby5qcyI7
Listening on http://0.0.0.0:8080

http://0.0.0.0:8080 にアクセスすると、Hello world!と表示されます。 deployctl を使って、アプリケーションを実行できました。

アプリケーションの作り方を確認

実行できることはわかったので、続けて自前でアプリケーションを作ってみます。

hello-worldの内容を確認します。

アプリケーションは、必ず addEventListenerfetch イベントをリッスンし、コールバック関数で処理させる必要があります。

addEventListener("fetch", (event) => {
  /* handle the FetchEvent here */
});

シンプルにHello World!を返すだけのサンプルは、以下のようになっています。

addEventListener("fetch", (event) => {
  const response = new Response("Hello World!", {
    headers: { "content-type": "text/plain" },
  });
  event.respondWith(response);
});

先に実行した https://deno.land/x/deploy/examples/hello.js は、内容が少し異なっていたので、こちらも見ておくと理解が深まると思います。

addEventListener("fetch", (event) => {
  event.respondWith(
    new Response("Hello world!", {
      status: 200,
      headers: {
        server: "denosr",
        "content-type": "text/plain",
      },
    })
  );
});

そのほかの実装例も充実しているので、これだけでかなり参考になります。

自前でアプリケーションを作る

今回は、デプロイができることを試したいので、簡単なものにとどめておきます。 アクセスすると、現在の日付と時刻を返すアプリケーションを作ります。

以下のソースコードを用意しました。

[main.ts]

addEventListener("fetch", (event) => {
  event.respondWith(handleRequest(event.request));
});

async function handleRequest(request: Request) {
  const date = new Date();
  const dateString = date.toLocaleDateString("ja-JP", {
    weekday: "long",
    year: "numeric",
    month: "long",
    day: "numeric",
  });
  const timeString = date.toLocaleTimeString("ja-JP", {
    hour12: false,
  });
  const message = `${dateString} ${timeString}`;

  const response = new Response(message, {
    headers: {
      "content-type": "text/plain;charset=utf-8",
    },
  });
  return response;
}

Deno Deploy にデプロイする

先に作成したアプリケーションを Deno Deploy にデプロイしてみます。

まずログイン

Deno Deploy にログインしましょう。GitHub 連携が使えます。

ログインすると以下の画面になります。

f:id:toranoana-lab:20210507135925p:plain

プロジェクト作成

プロジェクト名はランダムに生成してくれるので、今回はそのまま使います。

f:id:toranoana-lab:20210507135928p:plain

デプロイ元の指定

GitHub 連携を使う記事をよく見かけるので、Deploy URL を使う方法を紹介したいと思います。

Deploy URLを選択します。

f:id:toranoana-lab:20210507135949p:plain

main.ts を任意のサーバーにアップロードし参照できる状態にします。

公開している main.ts の URL を登録して Deploy します。

f:id:toranoana-lab:20210507135954p:plain

一瞬デプロイ画面が表示され、次の結果画面に遷移します。

f:id:toranoana-lab:20210507140003p:plain

ドメインが記載されているので、そちらにアクセスしてみます。

f:id:toranoana-lab:20210507140008p:plain

アクセスしてレスポンスを確認できました。 時刻がUTC になっているので、日本時間を取得できるように改修して更新してみます。

更新する

前述の通り Deno Deploy の実行基盤は UTC でした。日本時間を取得できるよう以下の通り改修します。

[main.ts]

addEventListener("fetch", (event) => {
  event.respondWith(handleRequest(event.request));
});

async function handleRequest(request: Request) {
  const date = new Date();
  const dateString = date.toLocaleDateString("ja-JP", {
    timeZone: "Asia/Tokyo", // タイムゾーン設定を追加
    weekday: "long",
    year: "numeric",
    month: "long",
    day: "numeric",
  });
  const timeString = date.toLocaleTimeString("ja-JP", {
    timeZone: "Asia/Tokyo", // タイムゾーン設定を追加
    hour12: false,
  });
  const message = `${dateString} ${timeString}`;

  const response = new Response(message, {
    headers: {
      "content-type": "text/plain;charset=utf-8",
    },
  });
  return response;
}

改めて、deploy URLから最初と同じようにデプロイします。

デプロイ後に再度アクセスすると、日本時間になっていました。 無事更新できました。

f:id:toranoana-lab:20210507140017p:plain

ログ

Deno Deploy のログは、console API で出力することができます。

ソースコードを次のように直してデプロイします。

[main.ts]

addEventListener("fetch", (event) => {
  event.respondWith(handleRequest(event.request));
});

async function handleRequest(request: Request) {
  const date = new Date();
  const dateString = date.toLocaleDateString("ja-JP", {
    timeZone: "Asia/Tokyo", // タイムゾーン設定を追加
    weekday: "long",
    year: "numeric",
    month: "long",
    day: "numeric",
  });
  const timeString = date.toLocaleTimeString("ja-JP", {
    timeZone: "Asia/Tokyo", // タイムゾーン設定を追加
    hour12: false,
  });

  // アクセス時刻としてログ出力
  const message = `${dateString} ${timeString}`;

  console.log(`access: ${message}`);
  const response = new Response(message, {
    headers: {
      "content-type": "text/plain;charset=utf-8",
    },
  });
  return response;
}

デプロイできたら、Logsを開きます。

f:id:toranoana-lab:20210507140021p:plain

console.log で出力した内容を確認できます。 f:id:toranoana-lab:20210507140052p:plain

ログレベルや、タイムスタンプも出せるので、実は今回のようにアクセス時刻をわざわざ残す必要はなかったりします。

現在の Deno Deploy

現在の Deno Deploy は、DB 機能を提供していません。データの永続化を外部のサービスに依存しています。 ドキュメントでは、 DB を使用する例として FaunaDB と AWS DynamoDB などの使い方を紹介しています。

deno.com

deno.com

詳細に手順が書かれているので順を追って進めれば、大きな苦労なくアプリケーションの構築ができるでしょう。

専用の DB も無い現状ですので、Redis などのキャッシュに使うようなインフラもありません。

こういったインフラがない現状なので、Deno Deploy だけで「なんでもできるという状況」ではありませんが、例えば AWS lambda で API を公開するようなユースケースで、「TypeScript で書きたい!」というニーズには非常に活躍するのではないでしょうか?

また注意点としては、Deno の API と Deno Deploy に公開されている API は一致しない点です。

例えば、次のソースコードは意図したよう動きません。

[version.ts]

addEventListener("fetch", (event) => {
  event.respondWith(handleRequest(event.request));
});

async function handleRequest(request: Request) {
  const message = `version: ${JSON.stringify((<any>Deno).version)}`;

  const response = new Response(message, {
    headers: {
      "content-type": "text/plain;charset=utf-8",
    },
  });
  return response;
}

deployctl を用いてローカルで動作させると、以下のように表示されますが、 f:id:toranoana-lab:20210507140055p:plain

Deno Deploy では、次のようになります。

f:id:toranoana-lab:20210507140111p:plain

API リファレンスに記載があるのですが、Deno DeployRuntime がサポートしている Deno API しか使えないので、確認しておくことは大事です。

deno.com


今回は Deno Deploy を試しました。
Deno Deploy は、始まったばかりのパブリックベータです。
実行環境を用意するということで、「これからの オープンソースソフトウェア の開発は、実行環境も提供していかないと普及できないのか」と思っています。 特に、サーバーサイドJavaScript、TypeScript の実行環境としては、Node.js もあることを考えれば、それくらいのアピールやインパクトが必要なのかもしれません。

これからが楽しみなので、Deno 本体のリリースと併せて追いかけて行きたいと思います。

P.S.

■ 採用情報

とらのあなでは、オタクなエンジニアを募集しています。
yumenosora.co.jp

カジュアル面談も随時開催中です。お申し込みはこちら!
yumenosora.connpass.com

■ ToraLab.fmスタートしました!

メンバーによるPodcastを配信中!是非スキマ時間に聞いて頂けると嬉しいです。
anchor.fm

■ Twitterもフォローしてくださいね!

ツイッターでも随時情報発信をしています。
twitter.com