[Webpack] webpack-dev-server で CORS を回避する方法 [setupProxy]
はじめに
Webサービスの開発で webpack-dev-server を使っていると、 CORS の問題が見つかることがあります。
回避の方法はいくつかありますが、今回は http-proxy-middleware を使う方法についてです。
開発環境と本番環境の切り替えで、ソースコードを変更しなくてよいのがメリットです。
https://github.com/chimurai/http-proxy-middleware
デメリットは、、、とくに思いつきませんでした。
環境について
基本的にはこれまでの記事で作ってきた React のプロジェクトです。
backend は json-server を動かしています。
URL は http://localhost:3000
にしています。
frontend は webpack-dev-server を動かしています。
URL は http://localhost:3001
にしています。
運用環境では frontend と backend を同じドメインで動作させる想定です。
そのため、frontend のソースコードに書かれているAPIのエンドポイント は /api/*
になっています。
axios.defaults.baseURL = '/api';
そのため、(何もしなければ)開発環境では frontend からのAPIリクエストは http://localhost:3001/api/*
に飛ぶことになり、APIが処理されなくなります。
つまり、開発しにくい (/・ω・)/
この環境であれば、frontendからのリクエスト先を直接 backend のURLに書き換えることでも動かせますが、そうすると運用環境では動かなくなりますし、APIが異なるドメイン(たとえばAWS上のAPIであるなど)であれば CORS の問題も発生します。
構築
http-proxy-middleware のインストール
create-react-app しているとすでに node_modules にいたりしますが、バージョンが古かったりとかもあるのでインストールしておきます。
npm install --save-dev http-proxy-middleware
setupProxy.js の作成
プロジェクトの /src
配下に setupProxy.js
を作ります。
内容はこんな感じ。
const { createProxyMiddleware } = require('http-proxy-middleware');
module.exports = function (app) {
app.use(createProxyMiddleware('/api', {
target: 'http://localhost:3000/',
secure: false,
pathRewrite: { '^/api/': '/' },
changeOrigin: true,
autoRewrite: true,
}));
}
今回は frontend からの /api/*
のリクエスト を /*
に変えて backend に要求したいので、pathRewrite でパスの書き換えも設定しています。
設定終わりです。
あとはいつも通り npm start
すると、プロキシの設定が含まれた形で webpack-dev-server が立ち上がります。
補足
プロキシサーバがあって、API が 外部にあるような場合には、プロキシサーバを超えなければいけません。
そういうときは https-proxy-agent
と組み合わせて使うことで、プロキシを超えられます。
https://github.com/TooTallNate/node-https-proxy-agent
インストールは npm install --save-dev https-proxy-agent
。
例として、環境変数のプロキシ設定を使うとき。
const HttpsProxyAgent = require('https-proxy-agent');
const { createProxyMiddleware } = require('http-proxy-middleware');
const PROXY = process.env.HTTPS_PROXY || process.env.HTTP_PROXY;
module.exports = function (app) {
app.use(createProxyMiddleware('/api', {
target: 'http://localhost:3000/',
secure: false,
pathRewrite: { '^/api/': '/' },
agent: new HttpsProxyAgent(PROXY),
changeOrigin: true,
autoRewrite: true,
}));
}