@@ -13,11 +13,14 @@ var path = require('path');
1313var chalk = require ( 'chalk' ) ;
1414var webpack = require ( 'webpack' ) ;
1515var WebpackDevServer = require ( 'webpack-dev-server' ) ;
16+ var historyApiFallback = require ( 'connect-history-api-fallback' ) ;
17+ var httpProxyMiddleware = require ( 'http-proxy-middleware' ) ;
1618var execSync = require ( 'child_process' ) . execSync ;
1719var opn = require ( 'opn' ) ;
1820var detect = require ( 'detect-port' ) ;
1921var prompt = require ( './utils/prompt' ) ;
2022var config = require ( '../config/webpack.config.dev' ) ;
23+ var paths = require ( '../config/paths' ) ;
2124
2225// Tools like Cloud9 rely on this.
2326var DEFAULT_PORT = process . env . PORT || 3000 ;
@@ -165,12 +168,54 @@ function openBrowser(port) {
165168 opn ( 'http://localhost:' + port + '/' ) ;
166169}
167170
171+ function addMiddleware ( devServer ) {
172+ // `proxy` lets you to specify a fallback server during development.
173+ // Every unrecognized request will be forwarded to it.
174+ var proxy = require ( paths . appPackageJson ) . proxy ;
175+ devServer . use ( historyApiFallback ( {
176+ // For single page apps, we generally want to fallback to /index.html.
177+ // However we also want to respect `proxy` for API calls.
178+ // So if `proxy` is specified, we need to decide which fallback to use.
179+ // We use a heuristic: if request `accept`s text/html, we pick /index.html.
180+ // Modern browsers include text/html into `accept` header when navigating.
181+ // However API calls like `fetch()` won’t generally won’t accept text/html.
182+ // If this heuristic doesn’t work well for you, don’t use `proxy`.
183+ htmlAcceptHeaders : proxy ?
184+ [ 'text/html' ] :
185+ [ 'text/html' , '*/*' ]
186+ } ) ) ;
187+ if ( proxy ) {
188+ if ( typeof proxy !== 'string' ) {
189+ console . log ( chalk . red ( 'When specified, "proxy" in package.json must be a string.' ) ) ;
190+ console . log ( chalk . red ( 'Instead, the type of "proxy" was "' + typeof proxy + '".' ) ) ;
191+ console . log ( chalk . red ( 'Either remove "proxy" from package.json, or make it a string.' ) ) ;
192+ process . exit ( 1 ) ;
193+ }
194+
195+ // Otherwise, if proxy is specified, we will let it handle any request.
196+ // There are a few exceptions which we won't send to the proxy:
197+ // - /index.html (served as HTML5 history API fallback)
198+ // - /*.hot-update.json (WebpackDevServer uses this too for hot reloading)
199+ // - /sockjs-node/* (WebpackDevServer uses this for hot reloading)
200+ var mayProxy = / ^ (? ! \/ ( i n d e x \. h t m l $ | .* \. h o t - u p d a t e \. j s o n $ | s o c k j s - n o d e \/ ) ) .* $ / ;
201+ devServer . use ( mayProxy ,
202+ // Pass the scope regex both to Express and to the middleware for proxying
203+ // of both HTTP and WebSockets to work without false positives.
204+ httpProxyMiddleware ( pathname => mayProxy . test ( pathname ) , {
205+ target : proxy ,
206+ logLevel : 'silent' ,
207+ secure : false ,
208+ changeOrigin : true
209+ } )
210+ ) ;
211+ }
212+ // Finally, by now we have certainly resolved the URL.
213+ // It may be /index.html, so let the dev server try serving it again.
214+ devServer . use ( devServer . middleware ) ;
215+ }
216+
168217function runDevServer ( port ) {
169- // Launch WebpackDevServer.
170- new WebpackDevServer ( compiler , {
171- // When an unrecognized URL is requested (e.g. localhost:3000/todos),
172- // assume that this is a single-page app, and serve index.html.
173- historyApiFallback : true ,
218+ var devServer = new WebpackDevServer ( compiler , {
174219 // Enable hot reloading server. It will provide /sockjs-node/ endpoint
175220 // for the WebpackDevServer client so it can learn when the files were
176221 // updated. The WebpackDevServer client is included as an entry point
@@ -188,7 +233,9 @@ function runDevServer(port) {
188233 watchOptions : {
189234 ignored : / n o d e _ m o d u l e s /
190235 }
191- } ) . listen ( port , ( err , result ) => {
236+ } ) ;
237+ addMiddleware ( devServer ) ;
238+ devServer . listen ( port , ( err , result ) => {
192239 if ( err ) {
193240 return console . log ( err ) ;
194241 }
0 commit comments