node.jsexpresswebpackwebpack-dev-serverwebpack-dev-middleware

Webpack: Cannot get index.html with express server middleware


I followed the official getting started instructions of webpack to setup a litte test project and config file. As they recommend, I use an express server with webpack middleware.

The setup

server.js:

const express = require('express');
const webpack = require('webpack');
const webpackDevMiddleware = require('webpack-dev-middleware');

const app = express();
const config = require('./webpack.config.js');
const compiler = webpack(config);

// Tell express to use the webpack-dev-middleware and use the webpack.config.js
// configuration file as a base.
app.use(
    webpackDevMiddleware(compiler, {
        publicPath: config.output.publicPath,
    })
);

// Serve the files on port 3000.
app.listen(3000, function () {
    console.log('Example app listening on port 3000!\n');
});

My directory folder looks like this:

- dist/
    - assets/
    - css/
    - bundle.index.html
    - bundle.about.html
    - index.html
    - about.html
- src/
    - fonts/
    - images/
    - sass/
    - templates/
        - about.html
        - index.html
    - ts/
        - abstracts/
        - utils/
        - pages/
            - about.ts
            - index.ts

An this is my webpack.config (removed unnecessary items for this purpose).

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");

module.exports = {
    mode: mode,
    entry: {
        index: './src/ts/pages/index.ts',
        about: './src/ts/pages/about.ts',
    },
    output: {
        filename: 'bundle.[name].js',
        path: path.resolve(__dirname, './dist'),
        clean: true,
        publicPath: '.',
        assetModuleFilename: 'assets/[name][ext][query]',
    },
    devServer: {
        port: 3000,
        sockPort: 3000,
        contentBase: path.resolve(__dirname, 'dist'),
    },
    plugins: [ 
        new HtmlWebpackPlugin({
            title: 'Index',
            filename: 'index.html',
            template: 'dist/index.html',
            chunks: ['index'],
        }),
        new HtmlWebpackPlugin({
            title: 'about',
            filename: 'about.html',
            template: 'dist/about.html',
            chunks: ['about'],
        }),
    ],
    module: {
        rules: [
            {
                test: /\.html$/i,
                loader: "html-loader",
            },
            // Support von versch. Grafiktypen
            {
                test: /\.(png|svg|jpg|jpeg|gif)$/i,
                type: 'asset/resource',
                generator: {
                    filename: './assets/images/[name][ext][query]'
                }
            },
            // Support von Fonts
            {
                test: /\.(woff|woff2|eot|ttf|otf)$/i,
                type: 'asset/resource',
                generator: {
                    filename: './assets/fonts/[name][ext][query]'
                }
            },
        ],
    },
    resolve: {
        extensions: ['.ts'],
        alias: {
            Style: path.resolve(__dirname, './src/sass'),
            Fonts: path.resolve(__dirname, './src/fonts'),
            Images: path.resolve(__dirname, './src/images'),
        }
    }
};

The problem

Running localhost:3000 in my browser, express returns Cannot get /.

Running localhost:3000 in my browser, express returns Cannot get / index.html.

Running localhost:3000/dist/index.html in my browser, express returns Cannot get dist/index.html.

So simply said, I cannot accees anything. Why? My config says that the dist directory should be used as root directory.

  devServer: {
        port: 3000,
        sockPort: 3000,
        contentBase: path.resolve(__dirname, 'dist'),
    },

Solution

  • Below values for the publicPath option should work:

    Complete example:

    webpack.config.js:

    const path = require("path");
    const HtmlWebpackPlugin = require("html-webpack-plugin");
    
    module.exports = {
      mode: "development",
      entry: {
        index: "./src/ts/pages/index.ts",
        about: "./src/ts/pages/about.ts",
      },
      output: {
        filename: "bundle.[name].js",
        path: path.resolve(__dirname, "./dist"),
        clean: true,
        publicPath: "",
      },
      plugins: [
        new HtmlWebpackPlugin({
          title: "Index",
          filename: "index.html",
          template: "src/templates/index.html",
          chunks: ["index"],
        }),
        new HtmlWebpackPlugin({
          title: "about",
          filename: "about.html",
          template: "src/templates/about.html",
          chunks: ["about"],
        }),
      ]
    };
    

    src/templates/index.html:

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
      <meta charset="UTF-8">
      <meta http-equiv="X-UA-Compatible" content="IE=edge">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>Document</title>
    </head>
    
    <body>
      index
    </body>
    
    </html>
    

    src/ts/pages/index.ts:

    console.log("index");
    

    server.js:

    const express = require("express");
    const webpack = require("webpack");
    const webpackDevMiddleware = require("webpack-dev-middleware");
    
    const app = express();
    const config = require("./webpack.config.js");
    const compiler = webpack(config);
    
    app.use(
      webpackDevMiddleware(compiler, {
        publicPath: config.output.publicPath,
      })
    );
    
    app.listen(3000, function () {
      console.log("Example app listening on port 3000!\n");
    });
    

    Result:

    enter image description here

    Package versions:

      "devDependencies": {
        "html-webpack-plugin": "^5.3.2",
        "webpack": "^5.51.1",
        "webpack-cli": "^4.8.0",
        "webpack-dev-server": "^4.0.0"
      },
      "dependencies": {
        "express": "^4.17.1",
        "webpack-dev-middleware": "^5.0.0"
      }