2

I have a front-end application bundled with webpack, which is served by and talks to a Node backend server.

Webpack hot dev server is running on 8080. Node backend is running on 1985.

I want to serve index.html from Node, but want assets served from the hot dev server during development. To achieve this I have:

Set an absolute publicPath value in webpack config:

  output: {
    publicPath: 'http://localhost:8080/'
  },

And used absolute URLs in index.html to point to the hot dev server:

<script src="http://localhost:8080/webpack-dev-server.js"></script>
<script src="http://localhost:8080/js/vendors.js"></script>
<script src="http://localhost:8080/js/bundle.js"></script>

So I can run the hot dev server and run my Node server and browse to http://localhost:1985. Everything is great.

But when I come to deploy / run in production, this is definitely not what I want. I'd like relative URLs for vendors.js and bundle.js and I definitely don't want to include the webpack-dev-server.js script.

I could use Handlebars or some other templating on the server to specify the absolute / relative paths, but it wouldn't provide a clean way of removing the hot dev server script. I could also have different index files for each setup, but this seems like it would quickly lead to bugs.

How can this be best be structured / deployed to enable use of the hot dev server in development, while still allowing for the whole thing to be deployed and served via Node in production?

duncanhall
  • 11,035
  • 5
  • 54
  • 86

2 Answers2

1

We're currently doing the templating approach you suggested for the paths and sorta mitigated the ugliness of the webpack-dev-server.js script tag by introducing an environment variable that specifies whether or not we're 'building' or 'developing'.

If you're using gulp as a task runner (we are), you can set them with process.env.NAME = VALUE.

If you're using npm builds you can add them via the command line with --NAME VALUE.

The very last step for our backend server then is to create the variables that then fit into our index.html template:

    <%
    // connect the hot-reload dev server
    if (mode === 'dev') {
        print("<script type='text/javascript' src='" + webpackURL + "/webpack-dev-server.js'></script>");
    }
    %>
    <script type="text/javascript" src="<%= webpackURL %>/js/bundle.js"></script>
suarezsm
  • 11
  • 1
  • 1
    Thanks, this is sort of what I'd been contemplating but it just doesn't feel entirely "right". Short of any other solutions though, it's good to know I'm not the only one who's approached it in this way. – duncanhall Mar 18 '15 at 17:47
0

For this very reason I stopped using webpack-dev-server and instead use the combination of webpack-dev-middleware / webpack-hot-middleware as the latter allow you to mount them in an existing express server.

My server basically does this:

const express = require('express');
const webpackDevMiddleware = require('webpack-dev-middleware');
const webpackHotMiddleware = require('webpack-hot-middleware');
const config = require('./webpack.config.js');

const app = express();

if (process.env.WEBPACK_DEV_SERVER === 'true') {
    const config = webpack(config);
    app.use(webpackDevMiddleware(compiler));
    app.use(webpackHotMiddleware(compiler));
} else {
    app.use(express.static(path.join(__dirname, './dist'));
}

app.use((req, res) => {
    res.status(200).send(`
        <!doctype html>
        <html>
        <head>
            <title>App</title>
        </head>
        <body>
            <div id="root"></div>
            <script src="/bundle.js"></script>
        </body>
        </html>
    `);
});

You can see a complete example in the 60fram.es react boilerplate

Richard Scarrott
  • 6,638
  • 1
  • 35
  • 46