Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Usage with an existing webserver #46

Closed
bilalq opened this issue Dec 14, 2014 · 10 comments
Closed

Usage with an existing webserver #46

bilalq opened this issue Dec 14, 2014 · 10 comments

Comments

@bilalq
Copy link

bilalq commented Dec 14, 2014

Before anything else, I wanted to express just how awesome I think this is.

That aside, I ran into some issues getting this to work in the kind of setup I wanted. I have an Express server that I want to use as a RESTful API and have the / route serve the React app. In prod, I just have it build out and serve the static assets, so there's no problem there.

However, I found it a little tricky to get the hot reload working with that kind of setup in development.

I saw this section on using the webpack dev server with an existing server on the docs, and that worked well enough for basic usage, but hot reloading failed since it would try to make requests against my main server rather than the webpack one for hot reload updates.

I managed to work around this by defining a set of webpack routes to proxy through all requests for static assets.

In /server/routes/webpack.js, I have:

var express = require('express')
  , request = require('request')
  , router = express.Router();

var webpackServerUrl = 'http://localhost:3001/';

// Proxy all requests through to the webpack server
router.get('/*', function(req, res) {
  request(webpackServerUrl.concat(req.baseUrl, req.url))
  .pipe(res);
});

module.exports = router;

and in /server/app.js:

// Use webpack server to serve static assets in development and express.static 
// for all other stages
if (app.get('env') === 'development') {
  var webPackServer = require('./routes/webpack');
  app.use('/scripts', webPackServer);
  app.use('/styles', webPackServer);
} else {
  app.use(express.static(path.join(__dirname, '..', 'build', 'client')));
}

And this is a rough skeleton of how things are structured:

.
├── client
│   ├── components
│   │   └── MyView.jsx
│   └── app.js
├── package.json
├── server
│   ├── app.js
│   ├── bin
│   │   ├── webpackDevServer
│   │   └── appServer
│   ├── middleware
│   │   └── errorHandler.js
│   ├── routes
│   │   ├── index.js
│   │   ├── users.js
│   │   └── webpack.js
│   ├── services
│   └── views
│       ├── error.jade
│       ├── index.jade
│       └── layout.jade
├── styles
│   └── app.scss
└── webpack.config.js

While this works, it seems like it's the wrong way to do it. I imagine this is a fairly common use-case, but I couldn't find any decent examples to support this. Is there a better approach to this than setting up a proxy like that?

@gaearon
Copy link
Owner

gaearon commented Dec 14, 2014

Hi, thank you for kind words. Have you looked at isomorphic-react-template?

@gaearon
Copy link
Owner

gaearon commented Dec 14, 2014

There is also isomorphic-hot-loader example. I haven't really dug into differences yet (since I'm not server-rendering myself just yet), but I think I need to document at least one of these approaches because it seems like a common issue nowadays.

Does any of these solve your problem?

@bilalq
Copy link
Author

bilalq commented Dec 14, 2014

I'm not terribly concerned with making the app isomorphic, but those were interesting reads, thanks. It seems all three of us are doing a variation on the same idea though.

None of us are using the webpack-dev-middleware though, and I wonder if that could be used as a mounted sub-app somehow.

From the looks of things, it seems proxying/redirecting is indeed the way to go.

@gaearon
Copy link
Owner

gaearon commented Dec 14, 2014

@sokra can you chime in to help? I wonder if there's a more proper way to do this.

@sokra
Copy link

sokra commented Dec 15, 2014

No need to proxy anything. The trick is to point publicPath to the dev-server port.

Example:

  • node.js server port 8080
  • webpack-dev-server port 2992

output.publicPath = "http://localhost:2992/_assets/"
<script src="http://localhost:2992/_assets/bundle.js"></script>
use the inlined mode (recommended) or set contentBase = "http://localhost:8080/

The webpack/react-starter does it this way:

@gpbl
Copy link

gpbl commented Jan 12, 2015

I prefer to use a proxy so I can open the web app on other devices maintaining relative urls.

@bilalq
Copy link
Author

bilalq commented Jan 13, 2015

Thanks for sharing the approach.

@kurtharriger
Copy link

i use a proxy as it avoids issues with cross origin resource requests. While you can and should handle cors headers for apis, browsers do not return good error information on 500 errors and using a proxy simplifies debugging during development.
Instead of having your api proxy requests you can do it the ither way around as well.
Webpack-dev-server can proxy request instead of redirecting by using contentBase: {target: 'http://localhost:8000' }. Note contentBase is now an object with a target instead of a string. This tells webpack to proxy rather than redirect.

@catamphetamine
Copy link

Don't know if it works uniformly (on server) but with new webpack and its new "proxy" parameter it works for me with webpack-dev-server and existing node webserver

@gaearon
Copy link
Owner

gaearon commented May 11, 2015

Not really an issue. Closing. See above for many working approaches :-).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants