🦕

Deno x DevContainer 開発環境構築|Offers Tech Blog

2023/03/27に公開

こんにちは! 副業転職プラットフォーム Offers を運営している株式会社 overflow でバックエンドエンジニアをしております、さわ(@hacksaw_a_)です!
今回は Deno と DevContainer を用いて開発環境を構築して得た知見を共有します!

Denoとは?

Deno はの次世代版 Node.js とも言われている JavaScript と TypeScript の実行環境です。
次世代版と言うだけあって環境構築し始めてから実際に開発を行えるまでがとても早かったり、イマドキな開発体験が得られたりと洗練されている印象を受けました。

あとゆるいディノサウルスが可愛い🦕🦕🦕

deno icon

Node.jsとの違い

  1. セキュリティ:Deno はデフォルトでアクセス制限がかかっており、アプリが安全に動作します。
  2. TypeScript対応:Deno は TypeScript を直接実行できるので、別途コンパイルが不要です。
  3. 依存関係の管理:Deno は URL を使ってモジュールをインポートし、簡単な構造で依存関係を管理できます。
  4. 標準ライブラリやLinterなど:Deno には豊富な標準ライブラリ・機能があり、パッケージを追加せずに多くの機能が使えます。

個人的には TypeScript 周りの設定が要らなかったり、当たり前に入れていた Prettier などの formatter が不要なのが嬉しいですね! Node.js の時は環境構築面倒くさかったんだなーと Deno の構築して気付かされました
(この手軽さ、もう Node.js には戻れない...🫠)

DevContainerとの組み合わせ

さらに DevContainer を併せて使うと開発がもっと楽になります!
DevContainer は開発環境を簡単に作れるツールで以下のメリットがあります。

  • ホストPCのOSの差異を吸収:DevContainer はコンテナ技術を使っているため、異なる OS のホスト PC でも同じ環境を作ることができます。
  • 独立した開発環境:コンテナ上で動作するため、ローカルの VSCode とは丸ごと別の環境を作れます。これにより、プロジェクトごとに環境を切り替えることが容易になります。

今回は友人と一緒に開発を進めることにしたのですが、私は Mac、友人は Windows だったのでホスト PC の OS 差異をなるべく消すために DevContainer を使ってみました。
ローカルの VSCode に Deno 用の拡張機能などを入れなくて良いのも良いですね!
僕の場合、しばらく色々な PJ で使われた VScode にはなんでこれが入ってるんだ? という拡張機能が入っていたりします😅

環境構築

この章では、DevContainer で Deno 環境を作るコードを掲載します。DevContainer のインストール手順などは省きますので、事前にインストールしておいてください。

ディレクトリ構成

root/
  ├ Dockerfile
  ├ docker-compose.yml
  └ .devcontainer/
    ├ devcontainer.json
    └ docker-compose.yml

コード

  1. ~/Dockerfile
FROM denoland/deno:1.30.3
WORKDIR /workspace
  1. ~/docker-compose.yml
version: "3"

services:
  deno_devcontainer:
    build:
      context: .
      dockerfile: Dockerfile
    container_name: deno_devcontainer
    volumes:
      - .:/workspace
    ports:
      - "8080:8080"
  1. .devcontainer/devcontainer.json
{
  "name": "Deno DevContainer",
  "dockerComposeFile": ["../docker-compose.yml", "docker-compose.yml"],
  "service": "deno_devcontainer",
  "workspaceFolder": "/workspace",
  "forwardPorts": [8080],
  "customizations": {
    "vscode": {
      "settings": {
        "deno.enable": true,
        "deno.lint": true,
        "deno.unstable": false
      },
      "extensions": [
        "denoland.vscode-deno"
      ]
    }
  }
}
  1. .devcontainer/docker-compose.yml
version: '3'

services:
  deno_devcontainer:
    command: /bin/sh -c "while sleep 1000; do :; done" # デフォルトのコマンドをオーバーライドして、プロセス終了後もシャットダウンしないようにする
  1. VSCode で「Remote-Containers: Reopen in Container」コマンドを実行しコンテナを起動

これで Deno 環境が構築され、DevContainer 内で開発を始められます。

Deno のサンプル

Deno は TypeScript に標準で対応しているので TypeScript で記述します。

ディレクトリ構成

  project_root/
    ├ .devcontainer/
    │  ├ devcontainer.json
    │  └ docker-compose.yml
++  ├ src/
++  │  └ main.ts
    ├ Dockerfile
    └ docker-compose.yml

コード

src/main.ts

import yahooFinance from "npm:yahoo-finance2";

async function getAppleStockPrice() {
  const symbol = "AAPL";
  const quote = await yahooFinance.quote(symbol);
  console.log(`Appleの現在の株価: $${quote.regularMarketPrice}`);
}

getAppleStockPrice();

Deno の実行

Deno は TypeScript を事前にコンパイルする必要はありません。以下のコードで実行します。

deno run --allow-net --allow-env src/main.ts

開発がしやすいように改善していく

今の状態では開発がしづらいので改善していきましょう。

Deno 周りの改善

npmライブラリをimportする際は esm.sh などから取得する

npm ライブラリを "npm:xxx" という記法でインポートすると、型ファイルが得られず、型の恩恵が受けられません。
そこで、esm.sh というツールを使うことで、型ファイルも同時にダウンロードして開発を進められます。
※esm.sh は、インターネット上にある npm(Node.js のパッケージマネージャ)ライブラリを Deno で使えるように変換するツールです。

これにより、型の恩恵を受けながらコードを書くことができます。

import 文を書いた直後はこのように表示されているかと思いますので

Uncached or missing npm package: "xxxx".

Uncached or missing npm package: "yahoo-finance2". deno(no-cache-npm)

クイックフィックスからライブラリを引っ張ってきてキャッシュしましょう(ここ、$ deno cache コマンドを上手く叩けばクイックフィックス使わなくてもいけそうなのですがまだよくわかってません🫠)

quick fix

ここで、 "npm:xxx" という記法だと VScode 上で型が表示されませんが...

cannot see type info

esm.sh を使う記法であれば型情報が参照できます!

can see type info

開発環境の改善

CLIで使うパッケージの導入

開発がラクになるように、~/Dockerfile に必要な CLI コマンドを追加します。
次のコードを追加することで、DevContainer 環境上で git や vim が使えるようになります。

RUN apt-get update && apt-get install -y git vim

.bashrc などの設定ファイルを DevContainer 環境上にマウント

ターミナルでの利便性を向上させるために、.bashrc や.vimrc を DevContainer 環境の /root 配下に配置します。
※設定内容はお好みで

今回は下記のディレクトリに配置します

  project_root/
    ├ .devcontainer/
    │  ├ devcontainer.json
    │  └ docker-compose.yml
++  ├ root/
++  │  ├ .bashrc
++  │  └ .vimrc
    ├ src/
    │  └ main.ts
    ├ Dockerfile
    └ docker-compose.yml

.devcontainer/docker-compose.yml

version: '3'

services:
  backend:
++  volumes:
++    - type: bind
++      source: "./root/.vimrc"
++      target: "/root/.vimrc"
++    - type: bind
++      source: "./root/.bashrc"
++      target: "/root/.bashrc"
    command: /bin/sh -c "while sleep 1000; do :; done" # デフォルトのコマンドをオーバーライドして、プロセス終了後もシャットダウンしないようにする

ここまできたら VScode で[Dev Containers: Rebuild Container Without Cache]をすることで bash や vim の設定を自由にいじれるようになりました!

まとめ

ここまでで、最低限ではありますが Deno の開発が DevContainer 環境上で完結するようになりました。
Docker や DevContainer の設定が主で、Deno の設定はほとんどせずに、TypeScript や Linter、Formatter を使えるのがすごいと思いませんか?
(Node.js を使ってきた人はきっと同じように感じたかと思います!)

個人的には npm で配布されているライブラリを使えるようになったことで、「もう Node.js をつかう理由がなくなったのでは?」と思っているくらい、Deno はシンプルで強力なバックエンドの選択肢だと思います。

今回の記事を参考に構築していただければローカル環境も汚れませんし、ぜひ Deno での開発にチャレンジしてみてください!

関連記事

Offers Tech Blog

Discussion