Node.jsアプリのCI/CDをCircleCI と CircleCI Orbsで簡単に構築する

Node.jsアプリのCI/CDをCircleCI と CircleCI Orbsで簡単に構築する

モダンなフロントエンド開発において、コードの品質を保ちながら効率的にデリバリーするには CI/CD パイプラインが欠かせません。本記事では、Vite と TypeScript で作成したプロジェクトへのCircleCI プロジェクトの基本的なセットアップから、Node.js Orb を使った効率的な CI 設定、そして Vite プロジェクトのビルドパイプライン構築までを順を追って見ていきます。

前提条件

基本的なアカウントセットアップなどについては省略します。以下の環境またはアカウントについては、各自で事前にセットアップしてください。

  • Node.js 環境がセットアップ済み
  • GitHub アカウント
  • CircleCI アカウント(GitHub と連携済み)

プロジェクトの準備

まずは、Vite で新しいプロジェクトを作成しましょう。

npm create vite

プロンプトに従って設定を進めます:

  • Project name: first-cci-app
  • Framework: Vanilla
  • Variant: TypeScript
  • Use rolldown-vite: No
  • Install and start: Yes

これで以下のような構成のプロジェクトが作成されます:

.
├── index.html
├── package-lock.json
├── package.json
├── public
│   └── vite.svg
├── src
│   ├── counter.ts
│   ├── main.ts
│   ├── style.css
│   └── typescript.svg
└── tsconfig.json

GitHub リポジトリへの push

プロジェクトを Git で管理し、GitHub に push します:

git init
git remote add origin git@github.com:your-username/practice-vite-app.git
git add .
git commit -m 'init'
git push origin main

これで準備完了です。

CircleCI プロジェクトのセットアップ

CircleCI のダッシュボードにアクセスし、新しいプロジェクトをセットアップしていきましょう。CircleCIのTOPページで「Set up a project」をクリックしましょう。

CircleCIに接続しているGitHubアカウントにあるリポジトリの一覧が表示されます。もしここで作成したリポジトリが表示されない場合は、GitHubとの連携設定をチェックしてください。CIパイプラインを作りたいプロジェクトを特定したら、「Set up」ボタンをクリックします。

セットアップオプションの選択

CircleCI におけるパイプラインのセットアップは、3つのオプションから開始できます。

  1. Fastest: リポジトリに既存の .circleci/config.yml を使用
  2. Faster: スターター CI パイプラインを新しいブランチにコミット(推奨)
  3. Fast: config.yml テンプレートを編集してから開始

今回は「Faster」を選択します。これにより、CircleCI が自動的に .circleci/config.yml を含むブランチを作成してくれます。

デフォルト設定の確認

CircleCI が生成するデフォルトの config.yml は以下のような内容になっています。リポジトリをチェックアウトして、”Hello, World”と出力するだけのとてもシンプルな内容ですね。

version: 2.1

jobs:
  say-hello:
    docker:
      - image: cimg/base:current
    steps:
      - checkout
      - run:
          name: "Say hello"
          command: "echo Hello, World!"

workflows:
  say-hello-workflow:
    jobs:
      - say-hello

とてもシンプルな内容ですが、CircleCIにおけるパイプラインの基本構造がおさえられています。。jobs では実行する処理の単位を定義し、docker で実行環境となるコンテナイメージを指定します。steps にはジョブ内で実行する処理を記述し、workflows でジョブの実行順序や条件を定義するといった具合です。

このデフォルト設定を push すると、すぐにパイプラインが実行され、”Hello, World!” が出力されます。

Node.js Orb を使って、Viteプロジェクトのビルドを実施する

これで1回目の CI パイプラインは実行できました。しかし現状では Vite アプリに向けたジョブはまだ何も設定されていません。そこでここからは Node.js プロジェクト用にパイプラインをカスタマイズしていきます。

Orbを利用して、Node.jsアプリのセットアップをショートカット

本来 CI ジョブ上で Node.js アプリをセットアップする際、以下のようなステップを定義する必要があります。

  • 過去のジョブから利用できるキャッシュがないか調べる
  • キャッシュがあれば利用する。なければnpm ci を実行
  • インストール結果を元に、キャッシュを更新

また、プロジェクトによってはnpmではなくpnpmyarnなどを利用しているケースもあり、パイプラインの設定はプロジェクトに応じて変更する必要があります。途中で利用するパッケージマネージャーを変えた場合も同様ですね。

CircleCIの場合、Orbという仕組みを利用してこれらの手間を省くことができます。

Orb とは

Orb は、CircleCI が提供する再利用可能な設定パッケージです。言語やツールに特化した設定をカプセル化しており、複雑な設定を簡潔に記述できます。Node.jsなど、主要な言語については、CircleCI が公式で Orbを提供しています。公式のNode.js ガイドを参考に、circleci/node Orb を導入しましょう。

config.yml の更新

config.yml を以下のように更新します。orbsというブロックが追加されていますが、ここではパイプライン上で利用する Orb の定義を実施しています。今回はcircleci/nodeのバージョン5.0.2を利用することが宣言されています。

version: 2.1
orbs:
  node: circleci/node@5.0.2

jobs:
  build_app:
    executor: node/default
    steps:
      - checkout
      - node/install-packages:
          pkg-manager: npm
      - run:
          command: npm run build
          name: Build app
      - persist_to_workspace:
          root: ~/project
          paths:
            - .

workflows:
  build_app_workflow:
    jobs:
      - build_app

ジョブについても変化があります。1つ目の変化が、Executor の指定です。

executor: node/default

これにより、Orb が提供するデフォルトの Node.js 実行環境を使用するようになります。よってこのジョブで利用する Docker イメージの設定やバージョン管理などの手間を省くことができます。

続いて、パッケージのインストールを見てみましょう。

- node/install-packages:
    pkg-manager: npm

この1ステップで、以下の処理がすべて自動化されます。まず package.json の確認、lockfile の判定(package-lock.json の検出)、キャッシュの復元と続きます。その後 npm install を実行し、キャッシュを保存、最後に一時リンクを削除するという流れが、この2行で実現しています。

実際のパイプライン実行画面を見ると、node/install-packages が以下のステップに展開されていることがわかります:

  • Checking for package.json
  • Determine lockfile
  • Restoring cache
  • Installing NPM packages
  • Saving cache
  • Remove temporary links

キャッシュを活用し、利用しているパッケージマネージャーに応じたコマンドを利用する設定を行うことは、CI / CD のジョブ実行時間を短縮し、アプリケーションの QA やデプロイの時間を短縮することにつながります。 CircleCI の Orb を活用することで、このようなチューニングについても CircleCI 側が提供するベストプラクティスを簡単に導入できます。

インストール周りを設定したら、あとはビルドの実行を定義しましょう。ビルドコマンドをジョブのステップに追加してあげましょう。

- run:
    command: npm run build
    name: Build app

最後にビルド結果をワークスペースに保存するステップを追加します。

- persist_to_workspace:
    root: ~/project
    paths:
      - .

ビルド成果物をワークスペースに保存しておくことで、後続のジョブ(デプロイなど)で利用できるようになります。

これでシンプルな Vite アプリをビルドするパイプラインが出来上がりました。

パイプラインの実行

設定を push すると、パイプラインが自動的に実行されます。CircleCI のダッシュボードで各ステップの進行状況を確認できます。

すべてのステップが成功すると、以下のような流れで処理が完了します。

  1. Checkout code (0s)
  2. Checking for package.json (0s)
  3. Determine lockfile (0s)
  4. Restoring cache (0s) – 初回は空
  5. Installing NPM packages (数秒)
  6. Saving cache (0s)
  7. Remove temporary links (0s)
  8. Build app (数秒)

2回目以降の実行では、キャッシュが効くため、パッケージインストールのステップについてはより短い時間で完了するようになります。今回はnpm create viteでセットアップしたばかりのアプリなので元々短時間でしたが、 React アプリや E2E テストでの Playwright インストールなどが追加されると、このキャッシュステップが次第に大きな効果を生み出すようになります。

まとめ

CircleCI では、 Orbを利用することでライブラリのインストールのような一般的・汎用的なタスクのジョブ定義を YAML から除外できます。全てのコマンドが Orb として公開されているわけではありませんが、パイプライン上でのキャッシュ管理や利用するパッケージマネージャーの選択など、パイプラインで実現したいこととは直接関係ない作業について考える手間を省けます。

他にもさまざまなOrbが公開されていますし、独自の private な orbを定義することも可能です。ぜひCircleCIを利用して、CI / CDパイプラインにおける「差別化されていない重労働」を削減しましょう。

Hidetaka Okamoto profile photo

Hidetaka Okamoto

ビジネスデベロップメント

DigitalCubeのBizDev。EC ASPの開発やStripeのDeveloper Advocateとしての経験を元に、SaaSやECサイトの収益を増やすための方法・生成AIを使った効率化や新しい事業モデルの模索などに挑戦する。