はじめに
Software Architecture について学ぼうとした矢先に、Nuxt.js(Vue.js)とGoでSPA + API(レイヤードアーキテクチャ)でチャットアプリを実装してみたという記事をみつけ、とても勉強になったため、1から自分でも実装してみることにしました。
これはその日記です。1日目はNuxtとGoで簡易的なstatic serverを作成しました。
NuxtのSkeletonの作成
client folerの配下に、nuxt_go_template folderを作成し、その中でnuxtをインストールします。
$ yarn create nuxt-app <project-name>
GoでSkeletonサーバ (static server) の作成
まずは、依存関係管理ツールのdepをインストールします(詳しくはこの記事を参考にしてください。)。
$ cd server
$ dep init
次に、server folder下にインフラ層を担当するinfra folderを作成し、さらにその配下に、routing技術を担当するrouter folderを作成します。
router folderの配下に、router.goを設置し、gorilla muxと呼ばれるhttp request multiplexerのpackageを利用してルーターをインスタンス化します。
package router
import (
"github.com/gorilla/mux"
)
// Router is the gorilla router for API.
var Router *mux.Router
func init() {
// Instantiation for gorilla Router.
r := mux.NewRouter()
Router = r
}
server配下のmain.goには静的ファイルをホスティングするサーバーを構築します。
package main
import (
"net/http"
"github.com/hideUW/nuxt_go_template/server/infra/router"
)
func main() {
// rootに対してnuxtのindex.htmlを返すように設定する。(ServeFile)
entrypoint := "../client/nuxt_go_template/dist/index.html"
router.Router.Path("/").HandlerFunc(ServeStaticFile(entrypoint))
// 静的ファイルの提供
// $PROROOT/_nuxt/ 以下のファイルに http://localhost:8080/_nuxt/~.html でアクセスできるように設定する。(FileServer)
router.Router.PathPrefix("/_nuxt/").Handler(
http.StripPrefix("/_nuxt/", http.FileServer(http.Dir("../client/nuxt_go_template/dist/_nuxt/"))))
// エラーハンドリング
if err := http.ListenAndServe(":8080", router.Router); err != nil {
panic(err.Error())
}
}
// 静的ファイルをホスティングする。
func ServeStaticFile(entrypoint string) func(w http.ResponseWriter, r *http.Request) {
fn := func(w http.ResponseWriter, r *http.Request) {
http.ServeFile(w, r, entrypoint)
}
return http.HandlerFunc(fn)
}
Goのhttp.Handlerやhttp.HandlerFuncをちゃんと理解するという記事を参考にすると以下のように動作している事がわかります。
http.Hundler
http.HandlerはServeHTTP
というメソッドを定義しているinterfaceです。このServeHTTPメソッドはHTTPリクエストを受けてHTTPレスポンスを返します。
type Handler interface {
ServeHTTP(ResponseWriter, *Request)
}
http.ServeMux のHandleメソッドの引数がこのinterface型になっています。
func (mux *ServeMux) Handle(pattern string, handler Handler) {
....
}
HandlerFunc
- func(ResponseWriter, *Request) を別の型として定義したものです。
- このHandlerFunc型にはServeHTTP(ResponseWriter, *Request)メソッドが実装されています。func(http.ResponseWriter, *http.Request) のシグネチャの関数を自分で定義しておき、このHandlerFuncにキャストするだけで構造体を宣言することなく http.Handler を実装することができます。
type HandlerFunc func(ResponseWriter, *Request)
// ServeHTTP calls f(w, r).
func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) {
f(w, r)
}
func hello(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
fmt.Fprintf(w, "Hello World")
}
func main() {
mux := http.NewServeMux()
mux.Handle("/hello", http.HandlerFunc(hello)) // helloをHandlerFuncにキャスト
}
- helloをhttp.HandlerFuncにキャストしています。
- http.HandlerFuncは ServeHTTP を実装しているので、ServeMux.Handleの第2引数に指定することが可能です。
おわりに
以下のコマンドを実行すると、Nuxtのindex.htmlが表示されて、ローカルホストを利用したstatic severが完成している事がわかります。
$ cd server
$ go run main.go
明日もがんばります。