フューチャー技術ブログ

denoに触れてみよう

春の入門祭り🌸の第10弾です

はじめに

6月よりTIGに入社した伊藤真彦です。入社時点ですでに春の入門祭りは始まっていたのですが、この度飛び入り参加で技術ブログを書かせていただける運びとなりました。

さて、初投稿として選んだテーマはdenoです。deno1.0のリリースからしばらくたちましたが、転職の合間に触って遊ぶことができましたので、体験記として紹介させていただきます。

この記事の内容

ただdenoをインストールして、hello worldのサンプルを動かすだけでは今から掲載するものとしては面白みに欠けるので、

1. docker上にインストールする
2. HTMLファイルを読みこんでレンダリングする

をゴールとします。

ファイルを用意しよう

今回必要なファイルは4種類です。

  1. Dockerfile
  2. docker-compose.yml
  3. main.ts
  4. hello.html

手始めにDockerfiledocker-compose.ymlを用意します、Ubuntuに突っ込む形をとりました。
コンテナ向きなミニマムなOSにしても良かったかもしれないです。
deno公式dockerイメージを作ろうぜ、みたいなissueを見た覚えがあるので、FROM denoとか1行書けば終わる日が来ることに期待します。

FROM ubuntu:18.04
WORKDIR /app
# deno導入シェルの実行&必要なライブラリをインストール、インストール完了後に削除
RUN apt-get -qq update && apt-get -qq -y install curl zip unzip \
&& curl -fsSL https://deno.land/x/install/install.sh | sh \
&& apt-get remove curl zip unzip
# pathを通す
RUN echo 'export DENO_INSTALL="/root/.deno"' >> ~/.bash_profile
RUN echo 'export PATH="$DENO_INSTALL/bin:$PATH"' >> ~/.bash_profile
docker-compose.yml
version: '3'
volumes:
vendor:
services:
app:
build: .
command: bash -c "source ~/.bash_profile && deno run --allow-net --allow-read app/main.ts"
ports:
- "8000:8000"
volumes:
- .:/app

執筆時点ではdenoは公式に記載の方法でインストールした後に手動でパスを通す必要があるので、その辺の作業をコンテナのビルド&起動時に行うのがミソです。
単にインストールを行うシェルを実行しただけではパスが通らずdenoコマンドが使えるようになりませんので注意。
(docker-composeの環境変数に書いてみるとかいろいろ試しつつ、うまく動くものをフィーリングで書いています、もう少しスマートな方法があるかもしれません)

denoコマンドのオプションはそれぞれ以下の意味です。
--allow-net: サーバーとして動かす上で通信を許可するオプション
--allow-read: HTMLファイルをdenoに探してもらう権限を与えるオプション

続いてサーバーを立ち上げるメインのTypeScriptと読みこみを行うHTMLを作成します。
メインのスクリプトはjsにちょっと型定義を付け足しただけの素朴なTypeScriptです。
ちなみにフューチャーにはTypeScriptに関する公式ガイドがあります、ぜひ確認してみてください。

今回はstdライブラリのreadFileStrでHTMLファイルを読んでみました。
正直この方法が正解か、他に方法があるのか自信がありませんが、そのうちフロントエンドライブラリが導入されて根本から使い方が変わっていくと思います、自由にやっていきましょう。

main.ts
import { serve } from "https://deno.land/std@0.50.0/http/server.ts";
import { readFileStr } from 'https://deno.land/std@0.53.0/fs/read_file_str.ts';
const s: any = serve({ port: 8000 });
const template: string = await readFileStr("app/html/hello.html");
console.log("server starting on http://localhost:8000/\nCtrl-C to shutdown container");
for await (const req of s) {
req.respond({ body: template });
}

HTMLもとてもシンプルですが、style要素が正常に動くかを見てみたかったので文字色を赤くしてみます。

hello.html
<html>
<body>
<h2 class="message">Hello Deno with Html</h2>
</body>
</html>
<style>
.message{
color: red;
}
</style>

上記4つのファイルを下記の構成で配置します。

HelloDeno(好きなフォルダ名)
├ app
│ ├ html
│ │ └ hello.html
│ └ main.ts
├ Dockerfile
└ docker-compose.yml

HTMLはpublic配下に置くべし、という意見もあるかもしれません。
今回は前職でお世話になったRuby on Railsの設計思想を引きずっており、MVCに属するものはapp配下に設置しました。
気が向いたらhtmlディレクトリの配下に複数のファイルを配置して拡張していくつもりで、このような構成になっています。
main.tsのHTML読み込み処理のパスを書き換えるだけで自由な構成にできるので、お好きなようにカスタマイズしてみてください。

起動

必要なファイルを準備できたら docker-compose up で起動します

ライブラリのダウンロード、コンパイルを経てサーバーが立ち上がります。
console.log("server starting on http://localhost:8000/\nCtrl-C to shutdown container");
で書いた内容がコンパイルが完了し、動いたタイミングで吐き出されています。
書かなくても動きますが、何かログ出力しておいた方が正常に動いているのか判定しやすいです。

無事に起動出来たらブラウザでlocalhost:8000にアクセスしましょう。
HTMLの内容が正常に表示されました!

まとめ

現状テンプレやお作法がそれほど世の中に出回っていないので、deno公式から使えそうなAPIやライブラリを探索しながら模索してみました。

HTMLファイルを取得して表示させることすら手探りな感じが黎明期を感じさせます。もう少し情報を漁ってベストな方法を探したり、フレームワークが誕生or参入してきたらこの記事に書いている手法は無意味になりそうですが、取り敢えず触ってみましたよ、以上、というお話なのでその辺はご容赦ください。

今後の発展が楽しみですね。