🐸

Vectyでページをリロードすると404 Not Foundになる

2023/07/24に公開

はじめに

この記事は,GolangのVectyというフレームワークを用いてwebフロントを開発している中で,routerを用いてページを移動した時は正常にレンダリングされるのに,URL直接打ち込みやリロードをすると404が返ってくる問題の解決策を個人的な備忘録としてまとめたものです.
GolangやVecty,その他のアップデートおよび仕様変更によって将来的にこの手順が使用できなくなる可能性があります.(記.2023/7/24)

前提条件

  • Vecty v0.6.0を使用している
  • ページ遷移にVecty Routerを使用している
  • (wasmserveを使用している)

事の始まり

ハッカソンで血迷ってGoのwasmを使って開発がしたい!ということになってVectyというフレームワークを使用していたのですが,環境構築中にトップページ以外でリロードすると404になってしまう問題に遭遇しました.
Vectyがある程度賑わっていたのは数年前の話で,当時はwasmではなくGopherJSが主流だったらしく,同じ状況に遭遇している物好き先駆者が見つからなかったので記事に残しておこうと思います.wasm使いたいならバイナリサイズの大きいGoじゃなくてRust使えば良いんだよなぁ

解決策

とりあえず色々調べてみたところ,Nuxt.jsやBlazer(C#のwebフロントフレームワーク)でも類似のissueが立っており,どうやらSPA全般に発生しうる現象というか仕様らしいです.
SPAは内部的にはパス/の1ページのみで成り立っており,リダイレクトを上手く使って疑似的にページ遷移を実現しているため,リダイレクトができない環境ではこの現象が発生するようです.
ということで,何らかの方法で表示する内容を/ページのものにすれば良いということが分かりました.これを実現するには複数の方法があると思いますが,今回はNginxを採用し,とりあえずDockerで正常に動作する環境を準備することができました.
DockerfileとNginxのdefault.confはこんな感じです.

FROM golang:1.18-alpine AS build

WORKDIR /build

COPY . .
RUN GOOS=js GOARCH=wasm go build -o main.wasm
RUN cp "$(go env GOROOT)/misc/wasm/wasm_exec.js" .

################################
FROM nginx:alpine
ENV TZ /usr/share/zoneinfo/Asia/Tokyo

ADD default.conf /etc/nginx/conf.d

WORKDIR /etc/nginx/html
COPY --from=build /build/index.html .
COPY --from=build /build/main.wasm .
COPY --from=build /build/wasm_exec.js .
COPY --from=build /build/assets ./assets

EXPOSE 8080
CMD ["nginx", "-g", "daemon off;"]
server {
  listen 8080;
  server_name localhost;

  location / {
    try_files $uri /index.html;
  }
}

やっていることはNginxのtry_filesを使用して全てのページでindex.htmlの内容を描画するように設定しているだけです.ついでにwasmのビルドとアプリの実行でDockerのステージを分けています.
この方法ではwasmserveが使えない(index.htmlのパス指定が必要)ため,ホットリロードが使えないというデメリットもありますが,とりあえず意図した通りに動作することを優先したため逐一Dockerをビルドする形で落ち着きました.

あとがき

実際にVectyで開発していたレポジトリはここにありますが,結局VectyではAPIを叩いた際の非同期処理の待機が上手くいかず,最終的にはこのディレクトリを全部吹き飛ばしてNext.jsで実装しました.
GoRoutineを使えばなんとかなりそうな雰囲気を感じたのでリベンジしたい気持ちもありますが,Goでwebフロントを実装するならKyotoというフレームワークがv2まで続いており現在も開発中なので,これで十分な気がします.

Discussion