0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Go+GinでReact Router利用のフロントページをホスティング

0
Last updated at Posted at 2025-12-17

概要・できること

本記事では、React Routerを設定したReact フロントエンドページをビルドして、

Go言語のWebフレームワークGinでホスティングする流れを記載します。

この記事のような設定をすることで、
Goでサーバー起動した時に、React Routerで指定されたパスに対してアクセスされても、正常にルーティングされたページが表示されるようになります。

なお、Ginで定義したAPIエンドポイントも共存利用が可能です。

前提:プロジェクトディレクトリの構成

今回取り上げるプロジェクトの構成は下記のようになっています。

  • プロジェクトルートにサーバーを起動するmain.goを配置
  • フロントエンドReactアプリはfrontend配下に配置
    • ビルドしたものはfrontend/dist/に配置される
.
├── frontend
│   ├── dist // <-------(Reactのビルド済みファイル群)
│   │   ├── assets
│   │   │   ├── index-DRSpbdMT.css
│   │   │   └── index-IRtkWgFT.js
│   │   ├── index.html
│   ├── package.json
│   ├── src
│       ├── App.tsx
│       :
├── src // <-------(サーバー用ソースコード一式)
│   ├─
│   :
│
├── main.go  // <------ サーバー起動用メインファイル

また、フロントエンドではReactRouterを使っており、App.tsxでルーティング設定を行なっています。

App.tsx
export default function App() {
    return (
        <BrowserRouter>
          <Routes>
            <Route path="/auth/signup" element={<Signup />} />
            <Route path="/auth/signin" element={<Signin />} />
            <Route element={<AuthedRoutes />}>
              <Route path="/" element={<PostNote />} />
              <Route path="/post" element={<PostNote />} />
              <Route path="/questions" element={<PostQuestions />} />
              <Route path="/diaries" element={<Diaries />} />
              <Route path="/auth/signout" element={<Signout />} />
            </Route>
          </Routes>
        </BrowserRouter>
    );
}

Goサーバーでのホスティング時の問題

Goサーバーで/にアクセスされた際だけ、frontend/dist/index.html等へアクセスするようなロジックを組むと、/auth/signin/post等へブラウザのURL欄で直接入力した場合にうまくReact Routerが使えません。

これは、

  1. 先にGin側のパスの解釈・レスポンスがあり、
  2. Reactページが開いてからReactRouterでのパス解釈・対応コンポーネント表示

という流れのためです。

解決:Ginサーバーで登録済みのAPI以外は静的ファイルを返す

解決策は、あらかじめ登録したAPIのパス以外は静的ファイルを探して、それをレスポンスとするものです。
下記のようなGo設定例となります。

main.go
func main() {
    //略
    
    // 先にAPIエンドポイントを宣言
    v1.GET("/api/diaries", diaryController.Get)
    v1.POST("/api/diaries", diaryController.Post)
    v1.DELETE("/api/diaries/:postId", diaryController.Delete)


    // 略
    // 後に静的ファイルへのルーティングの設定
	r.NoRoute(func(c *gin.Context) {
		_, file := path.Split(c.Request.RequestURI)
		ext := filepath.Ext(file)
		if file == "" || ext == "" {
			c.File("./frontend/dist" + "/index.html")
		} else {
			c.File("./frontend/dist" + c.Request.RequestURI)
		}
	})
    //略
}

アクセスされたくないファイルはdist配下へ入れないようにしましょう。
入れてしまうと、URLから当該ファイルへアクセス可能になってしまいます...。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?