skip to Main Content

I’m trying to build a react app with Webpack which reserves some path for HTML static files without importing them into react app, as in the example below.

Expected Result:

localhost:3000/any/other/path -> load React
localhost:3000/test.html -> load HTML file

Current Results

localhost:3000/any/other/path -> load React
localhost:3000/test.html -> redirect to localhost:3000/test -> load React (Default Route)

Here’s what I’ve tried.

  1. using html-webpack-plugin to define another HTML file

    plugins: [
      ...
      new HtmlWebpackPlugin({
        template: "./public/index.html",
        hash: true,
      }),
      new HtmlWebpackPlugin({
        template: "./public/test.html",
        filename: "test.html",
        chunks: []
      })
    ]
    
  2. using copy-webpack-plugin to copy the HTML file to the build directory.

Here is my webpack.config.js

require("dotenv").config();
const HtmlWebpackPlugin = require("html-webpack-plugin");
const path = require("path");
const webpack = require("webpack");
const { ModuleFederationPlugin } = webpack.container;
const deps = require("./package.json").dependencies;
const configs = require("./src/configs/build/configs.json");
configs.NPM_VERSION = require("./package.json").version;

const buildDate = new Date().toLocaleDateString();

module.exports = (_env, argv) => {
  return {
    entry: "./src/index.ts",
    mode: process.env.NODE_ENV || "development",
    output: {
      publicPath: `${configs.DOMAIN}/`,
    },
    devServer: {
      port: configs.PORT,
      open: true,
      historyApiFallback: true,
      hot: true,
      static: {
        watch: true,
      },
    },
    devtool: "source-map",
    resolve: {
      extensions: [".ts", ".tsx", ".js"],
    },
    module: {
      rules: [
        {
          test: /.(js|jsx|tsx|ts)$/,
          loader: "ts-loader",
          exclude: /node_modules/,
        },
        {
          test: /.(css|scss|sass)$/,
          use: ["style-loader", "css-loader", "postcss-loader"],
          exclude: /node_modules/,
        },
        {
          test: /.(png|svg|jpg|jpeg|gif)$/i,
          type: "asset/resource",
        },
        {
          test: /.html$/i,
          loader: "html-loader",
        },
        {
          test: /.tsx?$/,
          exclude: /node_modules/,
          use: [
            {
              loader: "dts-loader",
              options: {
                name: configs.APP_NAME,
                exposes: {},
                typesOutputDir: ".wp_federation",
              },
            },
          ],
        },
      ],
    },

    plugins: [
      new webpack.EnvironmentPlugin({ BUILD_DATE: buildDate }),
      new webpack.DefinePlugin({
        "process.env": JSON.stringify(configs),
      }),
      new HtmlWebpackPlugin({
        template: "./public/index.html",
        hash: true,
      })
    ],
  };
};

2

Answers


  1. Chosen as BEST ANSWER

    This is because when I run the serve command

    serve -s dist -p 3000
    

    The -s will resolve the symlink instead of showing 404. Somehow this option affects my public HTML file. If I revise it, then it works. BUT, this way, your react-router-dom will not work properly as the path that you're not specified in the router will lead to a 404 page instead of a default redirect.

    I end up setting up an express server inside my project to serve the static path separately.


  2. You should have a folder in your project root called public. Any HTML file places there will be relative to URL root.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search