3
votes

I have trouble in routing using react-router-dom and custom dev server using express, webpack-dev-middleware, webpack-hot-middleware.

This is my webpack config.

const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const webpack = require('webpack');

module.exports = {
    entry: [
        // 'react-hot-loader/patch',
        'webpack-hot-middleware/client?reload=true',
        './index.js'
    ],
    output: {
        filename: '[name].js',
        path: path.join(__dirname, './dist'),
        publicPath: '/',
        clean: true,
        chunkFilename: '[name].chunk.js',
    },
    mode: 'development',
    devtool: 'inline-source-map',
    module: {
        rules: [
            {
                test: /\.(js|jsx)$/,
                exclude: /node_modules/,
                use: ['babel-loader']
            },
            {
                test: /\.css$/,
                use: ['style-loader', 'css-loader']
            },
            {
                test: /\.s[ac]ss$/,
                exclude: /node_modules/,
                use: ['style-loader', 'css-loader', 'sass-loader']
            },
            {
                test: /\.(png|jpe?g|gif)$/,
                type: 'asset/resource'
            },
        ]
    },
    plugins: [
        new webpack.HotModuleReplacementPlugin(),
        new HtmlWebpackPlugin({
            template: path.join(__dirname, "public", "index.html"),
            title: 'Title'
        }),
    ],
    optimization: {
        splitChunks: {
            chunks: 'all',
        },
    },
}

This is my custom dev express server.js file

const express = require('express');
const webpack = require('webpack');
const webpackDevMiddleware = require('webpack-dev-middleware');
const webpackHotMiddleware = require('webpack-hot-middleware');
const path = require('path');
const fs = require('fs');
const app = express();
const config = require("./webpack.dev.config");

const compiler = webpack(config);

//Enable "webpack-dev-middleware"
app.use(webpackDevMiddleware(compiler, {
    publicPath: config.output.publicPath,
    stats: {
        chunks: false,
        hash: false,
        modules: false,
        version: false,
        assets: false,
        entrypoints: false,
        builtAt: false,
    }
}));

//Enable "webpack-hot-middleware"
app.use(webpackHotMiddleware(compiler));

app.use(express.static('./public'));


// serve the routes
app.get('*', (req, res) => {
     fs.readFile(path.join(compiler.outputPath, 'index.html'), (err, file) => {
        if (err) {
            res.sendStatus(404);
        } else {
            res.send(file.toString());
        }
    });
});

app.listen(8000, () => console.log('server listening on port 8000\n'))

When I open the application and all the routes are giving 404 not found. But when I add an option of writeToDisk to compiler options then everything is normal. I want the routes to work without writing to the disk. Any help is appreciated. Thanks in advance !!

This is my folder Structure

Folder Structure

1
Where is your index.html coming from? It looks like you rely on Webpack to produce or copy it to the public folder? If so, then you definitely need writeToDisk. Make sure it exists, if you try to read it from disk (which is what you are doing in fs.readFile(path.join(compiler.outputPath, 'index.html'))Domi
Yes, I'm have index.html file in public folder and I'm using it as a template to Htmlwebapckplugin. But the plugin creates a new index.html file right ? That's what is there in documentation. Is there any way to place it somewhere or what config should I use so that I don't need to write it to disk.Hem
The solution seems to be here: github.com/webpack/webpack-dev-middleware/issues/…Domi
Alternatively, the official documentation suggests using outputFileSystem.readFile*: github.com/webpack/webpack-dev-middleware#server-side-renderingDomi
@Domi Thanks a lot the app.use(instance) twice worked for me and can you tell me is my config work well with redux as well for development.Hem

1 Answers

2
votes

A solution to this problem was posted on the Github issue page here.

In order to use webpack-middleware to serve files from memory, without writing them to disk, while also being able to refer to the files explcitely (e.g. in res.render), the proposed solution is to add webpackMiddleware twice, before and after historyApiFallback, like so:

var webpackMiddleware = require("webpack-dev-middleware");
var historyApiFallback = require("connect-history-api-fallback");
var instance = webpackMiddleware(...);
app.use(instance);
app.use(historyApiFallback());
app.use(instance);