expresswebpackwebpack-dev-serverwebpack-dev-middleware

Cannot GET / error with my webpack-dev-middleware setup


First of all, I found many similar topics here but even after referring to them, I still haven't been able to get it working at all.

So, my problem simply is that I get Cannot GET / in Chrome when I visit localhost:3000 after running my express server (using npm run serve). It's not that it cannot find the bundle.js file; it simply cannot find the index.html.

I don't see any errors on the server console when I run npm run serve script in the package.json file. Webpack build (called from Webpack-dev-middleware) log shows no errors either.

It works correctly if I run webpack-dev-server directly from the terminal and visit to the same URL. (I have overridden the host and port to match the ones I am using in the express server, through devServer options in webpack.config.js.)

What am I doing wrong?

Folder structure

/client
    /main.js    
/dist
    /index.html
    /assets/
/server
    /server.js
/webpack.config.js
/package.json

webpack.config.js

const path = require('path');

module.exports = {
  entry: './client/main.js',

  output: {
    path: path.resolve(__dirname, 'dist/assets'),
    filename: 'bundle.js',
    publicPath: '/assets/'
  },

  module: {
    rules: [
      {
        use: 'babel-loader',
        test: /\.jsx?$/,
        exclude: /node_modules/,
      },
      {
        use: ['style-loader', 'css-loader', 'sass-loader'],
        test: /\.scss$/
      }
    ]
  },

  devServer: {
    host: 'localhost',
    port: 3000,
    historyApiFallback: true,
    contentBase: path.resolve(__dirname, 'dist'),
  }
};

/dist/index.html

<!DOCTYPE html>
<html>
  <head>
    <title>Webpack-Dev-Middleware Test</title>
  </head>
  <body>
    <div id="app-container">
    </div>
    <script src="/assets/bundle.js"></script>
  </body>
</html>

/server/server.js

const express = require('express');
const path =  require('path');
const app = express();
const port = process.env.PORT || 3000;

if (process.env.NODE_ENV !==  'production') {

  var webpackDevMiddleware = require("webpack-dev-middleware");
  var webpack = require("webpack");
  var config = require('./../webpack.config');
  var compiler = webpack(config);
  app.use(webpackDevMiddleware(compiler, {
    publicPath : config.output.publicPath,
  }));

} else {

  app.use(express.static(path.resolve(__dirname + '/../dist/')));
  app.get('*', (req, res) => {
    res.sendFile(path.resolve(__dirname + '/../dist/index.html'));
  });

}

app.listen(port, () => console.log('Started on port:', port));

Solution

  • The problem is that you don't really serve index.html anywhere in the webpack block. You should either use plugin such as html-webpack-loader to serve it on memory or use express's static function, which I think the more desirable (more webpack way) solution is the former one.

    Below is the example of using html-webpack-loader.

    (as one of the plugins in webpack config.)
    
    new HtmlWebpackPlugin({
      filename: 'index.html',
      template: './dist/index.html',
      title: 'Your website'
    })