1
0

使用技術

  • フロントエンド

    • Vite
    • React: ^18.2.0
    • YamadaUI: ^1.4.3
    • axios: ^1.7.2
    • react-router-dom: ^6.23.1
  • バックエンド(※外部サーバ)

    • FastAPI

React Router DOMでページルーティング

以下のような形でルーティングを定義していました。

App.tsx
// ...
const App = () => {
    return (
        <Routes>
            <Route path="/" element={<Home />} />
            <Route path="/about" element={<About />} />
            <Route path="/contact" element={<Contact />} />
        </Routes>
    );
}
// ...

ViteProxy

外部のバックエンドサーバとやりとりするため、Proxyを活用することで、サーバ内アクセスで完結できます。これをvite側で制御できます。

vite.config.ts
//...
export default defineConfig({
    // ...
    server:{
        cors: false,
        proxy:{
            "/api": {
                target: "[バックエンドサーバのベースパス]",
                // target: "http://127.0.0.1:3000", // Debugging
                changeOrigin: true,
                secure: false,
                rewrite: (path) => path.replace(/^\/api/, '')
            }
        }
    }
})

上記のように定義することで、[フロントエンドのベースパス]/api以降のルートは全て[バックエンドのベースパス]/以降のルートにリダイレクトされます。

例 ([front] => [back]

  • /api => /
  • /api/get_about => /get_about
  • /api/c/send_mail => /c/send_mail

したがって、axiosなどでバックエンドにfetchする場合は、以下のように短いパスでアクセスできます。

callApi.ts
await axios({
    method: POST,
    url: `/api/${/**[バックエンドサーバのエンドポイント]*/}`,
    headers: {
        'Access-Control-Allow-Origin': '*',
        'Content-Type': 'application/json',
    },
    data: /** [リクエストjsonデータ] */
})

ローカル環境ならここまでで開発可能です。(バックエンドもCORSを通しておけば)
しかしVercelにデプロイする場合、また違う設定が必要になるようでした

Vercelデプロイ

ViteProxyを有効にしてあげる

そのままでは、ViteProxyは有効にならず、Vercel側で同じような設定をしてあげる必要があります。

vercel.json
{ 
    "rewrites" :  [
        {
            "source": "/api/:path*",
            "destination": "[バックエンドサーバのベースパス]/:path*"
        }
    ] 
}

これで、ViteProxyが有効になり、同じようにリダイレクトされるようになります。

React Router DOMが機能しない

そのままvite環境としてデプロイすると、/以外のパス(/about/contactなど)が全て404 Not Foundになります。

image.png

VercelがReactのサブページを認識できてないようです。
先ほどのrewritesプロパティにその旨を設定してあげます。これで各ルートがベースパスを認識できるようになり、解消されます。

vercel.json
{ 
    "rewrites" :  [
        {
            "source": "/api/:path*",
            "destination": "[バックエンドサーバのベースパス]/:path*"
        },
        { 
             "source": "/(.*)", 
             "destination": "/" 
        }
    ] 
}

しかしこれにはトラップがありました。この設定によって、ViteProxyで設定した/api以降のルートは、全てReactRouterDOMのReactページだと認識されてしまうのです。
例えば、vercelデプロイ後の/api/get_aboutにアクセスしても、そんなページコンポーネントは存在しないので白紙のページが返ってきます。

解決策

めんどくさいですが、ReactRouterDOMのルーティングとViteProxyのルートを丁寧に書いてあげる必要があります。
ReactRouterDOMの場合はdestination/なので気をつけてください。

vercel.json
{ 
    "rewrites" :  [
        {
            "source": "/api/:path*",
            "destination": "[バックエンドサーバのベースパス]/:path*"
        },
        { 
             "source": "/about", 
             "destination": "/"
        },
        { 
             "source": "/contact", 
             "destination": "/" 
        },
    ] 
}
1
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
1
0