Webpack bundle served by express server - can't find bundle

Hi this is my express server which i'm trying to setup to use with webpack.

const Server = require('./server.js')
const path = require('path')
const port = (process.env.PORT || 3001)
const app = Server.app()

if (process.env.NODE_ENV !== 'production') {
  const webpack = require('webpack')
  const webpackDevMiddleware = require('webpack-dev-middleware')
  const webpackHotMiddleware = require('webpack-hot-middleware')
  const config = require('./webpack.config.js')
  const compiler = webpack(config)

  app.use(webpackHotMiddleware(compiler))
  app.use(webpackDevMiddleware(compiler, {
    noInfo: true,
    publicPath: path.join(__dirname, '/build')
  }))
}

app.listen(port)
  console.log(`Listening at http://localhost:${port}`)

./app.js

const path = require('path')
const express = require('express')

module.exports = {
  app: function () {
    const app = express();
    const indexPath = path.join(__dirname, '/build/index.html');
    const publicPath = express.static(path.join(__dirname, '/build'));

    app.use('/build', publicPath);
    app.get('/', function (_, res) { res.sendFile(indexPath) });

    return app;
  }
}

./server.js

var webpack = require('webpack');
var path = require('path');

var BUILD_DIR = path.resolve(__dirname, '/build');

var config = {
  entry: path.resolve(__dirname,'app/main.js'),
  output: {
    path: BUILD_DIR,
    filename: 'bundle.js',
    publicPath: '/build/'
  },
  module: {
    loaders: [
      { test: /\.jsx?$/, loader: 'babel-loader', exclude: /node_modules/, query: { presets: ['es2015', 'react']}},
      { test: /\.sass$/, loaders: ['style', 'css', 'sass'] },
      { test: /\.css$/, loader: "style!css" },
      { test: /\.png$/, loader: "url-loader?prefix=img/&limit=5000" },
      { test: /\.svg$/, loader: 'babel!svg-react' }
    ]
  }
};

module.exports = config;

./webpack.config.js

<!doctype html>
<html>
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>test</title>
  </head>
  <body>
    <div id="app">
      <script type="text/javascript" src="bundle.js"></script>
    </div>
  </body>
</html>

./build/index.html

When I run node app.js it finds the index.html page but i'm get a 404 error 'cannot find bundle.js' im sure somewhere im pointing to the wrong directory but i cannot seem to work it out!

Upvotes: 1

Views: 3296

Answers (1)

Michael Jungo
Michael Jungo

Reputation: 32972

When you're serving build/index.html on / it looks for the file /bundle.js (the directory you start your server from), which clearly doesn't exist. With your Webpack config you would create the file /build/bundle.js, if you ran Webpack.

Now here is where the webpack-dev-middleware comes in. Instead of creating that file, it serves the bundle from memory whenever the according path is hit. All you need to do, is tell the middleware that you want to serve the bundle on / by setting the publicPath in ./app.js.

app.use(webpackDevMiddleware(compiler, {
  noInfo: true,
  publicPath: '/'
}))

You also don't need to serve anything on /build. But if you want to use it to test the built bundle from your actual file system, you would need to run Webpack to generate that bundle. For that to work correctly you need to correct your BUILD_DIR to:

var BUILD_DIR = path.resolve(__dirname, './build');

The reason is that path.resolve treats /build as an absolute path and doesn't add it to the current directory. Which would also throw a permission denied error unless you run it as root. For more information see: https://nodejs.org/docs/latest/api/path.html#path_path_resolve_paths

Upvotes: 1

Related Questions