Skip to content

Commit fad0a2a

Browse files
committed
Add proxy option to package.json
This allows users to avoid CORS in simple projects that are hosted on the same server as backend.
1 parent 156a3c6 commit fad0a2a

File tree

2 files changed

+55
-3
lines changed

2 files changed

+55
-3
lines changed

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
"babel-runtime": "6.11.6",
4747
"case-sensitive-paths-webpack-plugin": "1.1.2",
4848
"chalk": "1.1.3",
49+
"connect-history-api-fallback": "1.2.0",
4950
"cross-spawn": "4.0.0",
5051
"css-loader": "0.23.1",
5152
"detect-port": "1.0.0",
@@ -61,6 +62,7 @@
6162
"fs-extra": "0.30.0",
6263
"gzip-size": "3.0.0",
6364
"html-webpack-plugin": "2.22.0",
65+
"http-proxy-middleware": "0.17.0",
6466
"jest": "14.1.0",
6567
"json-loader": "0.5.4",
6668
"opn": "4.0.2",

scripts/start.js

Lines changed: 53 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,14 @@ var path = require('path');
1313
var chalk = require('chalk');
1414
var webpack = require('webpack');
1515
var WebpackDevServer = require('webpack-dev-server');
16+
var historyApiFallback = require('connect-history-api-fallback');
17+
var httpProxyMiddleware = require('http-proxy-middleware');
1618
var execSync = require('child_process').execSync;
1719
var opn = require('opn');
1820
var detect = require('detect-port');
1921
var prompt = require('./utils/prompt');
2022
var config = require('../config/webpack.config.dev');
23+
var paths = require('../config/paths');
2124

2225
// Tools like Cloud9 rely on this
2326
var DEFAULT_PORT = process.env.PORT || 3000;
@@ -155,16 +158,63 @@ function openBrowser(port) {
155158
opn('http://localhost:' + port + '/');
156159
}
157160

161+
function addMiddleware(devServer) {
162+
// `proxy` lets you to specify a fallback server during development.
163+
// Every unrecognized request will be forwarded to it.
164+
var proxy = require(paths.appPackageJson).proxy;
165+
devServer.use(historyApiFallback({
166+
// For single page apps, we generally want to fallback to /index.html.
167+
// However we also want to respect `proxy` for API calls.
168+
// So if `proxy` is specified, we need to decide which fallback to use.
169+
// We use a heuristic: if request `accept`s text/html, we pick /index.html.
170+
// Modern browsers include text/html into `accept` header when navigating.
171+
// However API calls like `fetch()` won’t generally won’t accept text/html.
172+
// If this heuristic doesn’t work well for you, don’t use `proxy`.
173+
htmlAcceptHeaders: proxy ?
174+
['text/html'] :
175+
['text/html', '*/*']
176+
}));
177+
if (proxy) {
178+
if (typeof proxy !== 'string') {
179+
console.log(chalk.red('When specified, "proxy" in package.json must be a string.'));
180+
console.log(chalk.red('Instead, the type of "proxy" was "' + typeof proxy + '".'));
181+
console.log(chalk.red('Either remove "proxy" from package.json, or make it a string.'));
182+
process.exit(1);
183+
}
184+
185+
// Otherwise, if proxy is specified, we will let it handle any request.
186+
// There are a few exceptions which we won't send to the proxy:
187+
// - /index.html (served as HTML5 history API fallback)
188+
// - /*.hot-update.json (WebpackDevServer uses this too for hot reloading)
189+
// - /sockjs-node/* (WebpackDevServer uses this for hot reloading)
190+
var mayProxy = /^(?!\/(index\.html$|.*\.hot-update\.json$|sockjs-node\/)).*$/;
191+
devServer.use(mayProxy,
192+
// Pass the scope regex both to Express and to the middleware for proxying
193+
// of both HTTP and WebSockets to work without false positives.
194+
httpProxyMiddleware(pathname => mayProxy.test(pathname), {
195+
target: proxy,
196+
logLevel: 'silent',
197+
secure: false,
198+
changeOrigin: true
199+
})
200+
);
201+
}
202+
// Finally, by now we have certainly resolved the URL.
203+
// It may be /index.html, so let the dev server try serving it again.
204+
devServer.use(devServer.middleware);
205+
}
206+
158207
function runDevServer(port) {
159-
new WebpackDevServer(compiler, {
160-
historyApiFallback: true,
208+
var devServer = new WebpackDevServer(compiler, {
161209
hot: true, // Note: only CSS is currently hot reloaded
162210
publicPath: config.output.publicPath,
163211
quiet: true,
164212
watchOptions: {
165213
ignored: /node_modules/
166214
}
167-
}).listen(port, (err, result) => {
215+
});
216+
addMiddleware(devServer);
217+
devServer.listen(port, (err, result) => {
168218
if (err) {
169219
return console.log(err);
170220
}

0 commit comments

Comments
 (0)