はじめに
Web アプリケーションを開発する際、アーキテクチャの選択は常に悩ましい問題です。「巨大なモノリスは開発が進むにつれて複雑化し、マイクロサービスは管理が煩雑になる…。」そんなジレンマを抱えている開発者は少なくないでしょう。
特に、社内管理ツールや小規模な Web サービスを開発する際に、「単機能でシンプルに保ちたいけれど、ユーザー体験(UX)も妥協したくない」というニーズは非常に高まっています。
この記事では、そんな課題を解決するための一つの答えとして、Go 言語の単一バイナリとモダンなフロントエンド技術(DaisyUI + HTMX)を組み合わせた、新しい Web アプリケーションの形を提案します。
実際に動作するサンプルプロジェクトは、ここで公開しています。
このアーキテクチャが目指すもの
このアプローチのゴールは、以下の 2 つの要素を両立させることです。
- 圧倒的な管理のしやすさ: すべてのリソース(HTML, CSS, JavaScript)を Go の実行ファイルに埋め込むことで、デプロイは単一のバイナリファイルをコピーするだけで完了します。依存関係やランタイムの心配はもういりません。
- 高品質な Web UI: Go のサーバーサイドレンダリングを基本としつつも、DaisyUI(Tailwind CSS)で美しい UI を迅速に構築し、HTMX で JavaScript をほとんど書かずにリッチな動的体験を実現します。
これにより、「モノリシックな開発のシンプルさ」と「関心事の分離によるメンテナンス性」のいいとこ取りを目指します。
なぜこの技術スタックなのか?
バックエンド: Go + Echo + embed
- Go 言語: コンパイルが高速で、クロスプラットフォーム対応のシングルバイナリを簡単に生成できます。標準ライブラリも強力です。
- Echo フレームワーク: 高性能で拡張性の高い、Go の Web フレームワークです。ルーティングやミドルウェアの扱いが直感的で、迅速な開発をサポートします。
embed
パッケージ: Go 1.16 から導入された標準機能で、これにより静的ファイルやテンプレートをコンパイル時にバイナリに埋め込むことができます。これが「単一バイナリ」の鍵となります。
// web/web.go
package web
import (
"embed"
// ...
)
//go:embed templates static
var content embed.FS // templatesとstaticディレクトリの内容をバイナリに埋め込む
// ...
//go:embed
というディレクティブ一行で、指定したディレクトリがコンパイル後のバイナリに内包されます。
フロントエンド: DaisyUI + HTMX
- Tailwind CSS & DaisyUI: Tailwind CSS は、ユーティリティファーストな CSS フレームワークで、デザインの自由度を保ちながら効率的にスタイリングが可能です。DaisyUI は、その上に構築されたコンポーネントライブラリで、「ボタン」や「カード」といった UI 部品をクラス名だけで美しく実装できます。
- HTMX: 「なぜ JSON をやり取りするためだけに JavaScript をたくさん書く必要があるんだ?」という発想から生まれたライブラリです。HTML の属性としてサーバーへのリクエストを記述するだけで、サーバーから返された HTML フラグメントをページの特定の部分に差し込むことができます。これにより、React や Vue のような大規模なフレームワークを導入することなく、インタラクティブな UI を実現できます。
<!-- web/templates/index.html -->
<!-- ボタンをクリックすると/helloにGETリクエストを送信し、
結果をid="message-area"の要素に差し込む -->
<button
class="btn btn-primary mt-4"
hx-get="/hello"
hx-target="#message-area"
hx-swap="outerHTML"
>
メッセージを更新
</button>
<div id="message-area" class="mt-4 p-4 border rounded-md bg-base-200"></div>
アプリケーションの仕組み
リクエストが来てからブラウザにページが表示されるまでの流れは非常にシンプルです。
- 起動:
main.go
がアプリケーションを起動し、Echo サーバーを立ち上げます。 - リクエスト受付: Echo のルーターがリクエストを受け取り、対応するハンドラ関数を呼び出します。
- テンプレートレンダリング: ハンドラは
c.Render()
を呼び出し、Go のhtml/template
エンジンを使って HTML を生成します。このとき、embed
されたテンプレートファイル(index.html
やbase.html
)が使われます。 - レスポンス返却: 生成された HTML がブラウザに返されます。
- 動的更新 (HTMX): ユーザーが HTMX が適用された要素(例:ボタン)を操作すると、指定されたエンドポイントに非同期リクエストが送信されます。サーバーは HTML の断片(フラグメント)を返し、HTMX がそれをページの適切な場所に差し込みます。ページ全体のリロードは発生しません。
この構成により、バックエンドは Go のロジックに集中でき、フロントエンドは HTML と CSS(クラス名)中心で記述できるため、関心事がきれいに分離されます。
動作環境
WSL2上で作成/確認しています。
- WSL2
- ubuntu 24.04
- golang 1.23.11
- nodejs v22.17.0
どうやって始めるか?
このテンプレートを試すのはとても簡単です。
1. リポジトリをクローン
git clone https://github.com/KenichiTanino/golang_echo_onebinary.git
cd golang_echo_onebinary
2. 依存関係をインストール
# Goモジュール
go mod tidy
# Node.jsパッケージ (Tailwind CSS/DaisyUI用)
npm install
3.フロントエンドアセットを準備
既にリポジトリにあるファイルを使用しても構いません
# HTMXライブラリをダウンロード
curl -o web/static/js/htmx.min.js https://unpkg.com/htmx.org@1.9.10/dist/htmx.min.js
# CSSをビルド
npx tailwindcss -i ./assets/input.css -o ./web/static/css/app.css --minify
4. 開発サーバーを起動
go run ./cmd/app
ブラウザで `http://localhost:8080` を開いてみてください。
5. バイナリビルド
go build -o myapp ./cmd/app
生成された `myapp` という単一のファイルが、今回のアプリケーションです。このファイルをサーバーにコピーして実行するだけで、デプロイは完了です。
まとめ
Go 言語による単一バイナリのシンプルさと、DaisyUI + HTMX によるモダンなフロントエンド開発の生産性を組み合わせることで、管理が容易でありながら高品質な UI を持つ Web アプリケーションを効率的に構築できます。
このアプローチは、以下のようなプロジェクトに特に有効です。
- 社内向けの管理画面やダッシュボード
- 設定変更やステータス確認のための Web UI を持つ CLI ツール
- IoT デバイスの管理インターフェース
- 小〜中規模の Web サービス
「マイクロサービスはまだ早い、でもモノリスは避けたい」——そんな状況に対する現実的で強力な解決策として、この「Go 製シングルバイナリ Web アプリ」をぜひ試してみてはいかがでしょうか。