Skip to content

Commit 379cf5c

Browse files
authoredAug 4, 2016
Add proxy option to package.json (wmonk#282)
This allows users to avoid CORS in simple projects that are hosted on the same server as backend.
1 parent 156a3c6 commit 379cf5c

File tree

2 files changed

+55
-3
lines changed

2 files changed

+55
-3
lines changed
 

‎package.json

+2
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

+53-3
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)