【Vite+React】proxyでaxiosにドメインを入れないようにしよう

# Viteって誰

これまで割とのんびり個人で開発してきたおかげで、NextjsやNuxtjsに触れてから、`create-react-app`をしなくなりました。そんな中どうしてもバックエンドを分離しなければならない状況になり、久しぶりに`create-react-app`を叩きこもうと考えていました。

しかし`create-react-app`は2022年4月で開発が止まってしまったので、今では違うバンドラが流行ってます。

それがこいつ

https://vitejs.dev/

```terminal
$ npm create vite@latest

> npx
> create-vite

✔ Project name: … vite-project
✔ Select a framework: › React
✔ Select a variant: › TypeScript + SWC

Scaffolding project in /Users/**/vite-project...

Done. Now run:

  cd vite-project
  npm install
  npm run dev

```

`http://localhost:5173/`

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3092163/78567dcb-ad2c-eb96-90bd-68ba3ed2ed71.png)


# axiosって何者
JavaScriptを使ったことがある人は知ってるかもしれませんが、要するに`fetch()`です。
わからない人向けに言うと、いわゆる他サーバにリクエストを送ってレスポンスを受け取るまでをやってくれる便利なやつですね。今回の要件ではバックエンドが別サーバにあるので使わざるを得ません。

よく`fetch vs axios`みたいな記事があったりします。

https://apidog.com/jp/blog/fetch-vs-axios/

私が`axios`を選んだ理由は圧倒的にエラーハンドリングのやりやすさをとりました。（今回はハンドリングそんな厳しくやりません）
```terminal
$ npm i axios
```

とりあえず`axios`で、特定のAPIと通信する関数をつくります
ジェネリクスとか使ってますが、本当はカスタム型ガードを自作しないとチェックしてくれません
※`https://example.com/`は例です
```typescript:callAPI.ts
import axios, { AxiosError, AxiosPromise } from "axios";

export const callAPI = async <ReqT, ResT>(endpoint: string, method: string, data?: ReqT): AxiosPromise<ResT> => {
    const response_data = 
        await axios({
            method: method,
            url: "https://example.com/" + endpoint,
            data: data
        }).then((response) => {
            return response.data;
        }).catch((error: AxiosError) => {
            throw error;
        });

    return response_data;
}
```

これをテキトーなコンポーネントで呼んでみます。
```typescript:App.tsx
// ...中略
  useEffect(() => {
    callAPI("/", "GET")
    .then((response) => {
      console.log(response);
    }).catch((error) => {
      console.error(error);
    });
  }, []);
// ...中略
```

ちゃんと返ってきます、
```console:console
{message: 'Hello World!'}
```

しかしこれでは`https://example.com/`が丸見え

# viteのproxyを使おう
`vite.config.ts`に以下を定義しておきます。

```typescript:vite.config.ts
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react-swc'

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [react()],
  server:{
    proxy:{
        "/api": {
            target: "https://example.com",
            changeOrigin: true,
            rewrite: (path) => path.replace(/^\/api/, '')
        }
    }
  }
})

```

このようにすることで、`/api`以下のエンドポイントは、`https://example.com`以下のエンドポイントとして扱われます。仮に`http://localhost:5173/api`にアクセスすると、

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3092163/e13d37d4-3a2b-d225-4f89-1c438a8af863.png)

が返ってきます。
したがって先ほどのcallAPI関数も、

```diff_typescript:callAPI.ts
import axios, { AxiosError, AxiosPromise } from "axios";

export const callAPI = async <ReqT, ResT>(endpoint: string, method: string, data?: ReqT): AxiosPromise<ResT> => {
    const response_data = 
        await axios({
            method: method,
-            url: "https://example.com/" + endpoint,
+            url: "/api" + endpoint,
            data: data
        }).then((response) => {
            return response.data;
        }).catch((error: AxiosError) => {
            throw error;
        });

    return response_data;
}
```
このようにすることで、同じ呼び方でドメインを見えなくできます。
```console:console
{message: 'Hello World!'}
```