Created by: gaearon
(The proposal was updated since the original posting.)
This is a proof of concept of solution to #147 (closed). It works for simple cases, and I think it’s fairly unobtrusive.
It lets you add a field to package.json
like this:
"proxy": "http://localhost:3001",
Then any unrecognized requests (i.e. aren’t request to bundled assets) will be forwarded to that base URL. This is very similar to how our existing /index.html
fallback works for client side routing.
There is one gotcha: of course /index.html
fallback and proxy
(when specified) would compete. I resolved this with a heuristic that I think would work in the vast majority of cases.
If proxy
is specified, we make /index.html
fallback a little bit less aggressive, and we only activate it if specifically text/html
is present in the accept
header. In practice every modern browser (not IE8 but we don’t support it anyway) sends it when you navigate to a page, so /index.html
fallback will keep on working just fine for client-side apps. However, if you use fetch()
, $.ajax()
, axios()
or XMLHttpRequest
without explicitly putting text/html
there, we will happily proxy your request to devProxy
.
To illustrate this:
Open /todos/completed in browser
* browser sends "text/html" as part of "accepts" header
* we know that we want to redirect this to /index.html
* client side router takes over
fetch('/api/todos/completed')
* fetch (or alternatives) don't send "text/html" as part of "accepts" header by default
* devProxy was specified so we don't want to redirect this to /index.html
* instead, we forward this to devProxy
When proxy
is not specified, /index.html
fallback kicks in every time, just like now. So this behavior is completely opt-in.
If for some reason the heuristic fails for your project (maybe you just have to fetch()
some HTML... templates?), well, you can’t use proxy
. It is only a convenience. Please use the regular method (which is not that hard anyway—you’d have to add CORS to your server and hardcode the server URL into your client, just like you would do now anyway).
I feel this could be a good compromise that lets people get started without worrying about CORS.