0

I am trying to set up a new react project with a custom webpack config, and react router. I am using react 18, webpack 5, and react-router 6.

Looking at my App.tsx, it sets up some routes. For now, a few page components are lazy-loaded using React.lazy and Suspense:

import React, { Suspense } from "react";
import { BrowserRouter, Outlet, Route, Routes } from "react-router-dom";

const CarsPage = React.lazy(() => import("pages/cars"));
const PlanesPage = React.lazy(() => import("pages/planes"));


export const App: React.FC = () => {
  return (
    <BrowserRouter>
      <Routes>
        <Route
          element={
            <div>
              <HeaderBar />
              <Outlet />
            </div>
          }
        >
          <Route path="/" element={<div>Homepage here</div>} />
          <Route
            path="/cars/*"
            element={
              <Suspense fallback={<div>Loading . . .</div>}>
                <CarsPage />
              </Suspense>
            }
          />
          <Route
            path="/planes/*"
            element={
              <Suspense fallback={<div>Loading . . .</div>}>
                <PlanesPage />
              </Suspense>
            }
          />
        </Route>
      </Routes>
    </BrowserRouter>
  );
};

I am trying to set up my webpack to codesplit, such that the code for CarsPage or PlanesPage is bundled separately. Following the webpack instructions on codesplitting, this is my webpack config:

module.exports = {
  entry: "./src/index.tsx",
  target: "web",
  output: {
    path: path.resolve(__dirname, "../build"),
    publicPath: "/",
    filename: "[name].js",
    chunkFilename: "[id].[chunkhash].js",
  },
  optimization: {
    splitChunks: {
      chunks: "all",
      cacheGroups: {
        vendors: {
          test: /[\\/]node_modules[\\/]/,
          name: "vendor",
          chunks: "all",
        },
      },
    },
  },
  resolve: {... some resolve rules},
  module: {...some module rules}
  plugins: [...some plugins],
}

When I load the page, I see that the vendor chunk is correctly separate from the main chunk. (This is also desired, as I want my node_modules to be treated as a separate chunkfile, as they'll get updates far less often than the production bundle, so cacheing node_modules in the vendorfile is desired).

Running a build, I am not seeing separate chunk files for the CarsPage and PlanesPage components. Running with webpack dev server, when I load the page, I see a massive main.js file. Navigating to /cars or /planes, no additional js chunk is requested. Clearly, my code is not being split.

I have also tried using one of the new data routers with react-router 6 with the lazy property, similar to what is being done in the question Lazy loading routes in react router v6

What am I doing wrong with my setup here? I know create-react-app used to do this automatically, but how can this be acheived with a custom webpack config? Shouldn't anything imported using the React.lazy import be automatically code-split using webpack 5?

1 Answer 1

2

So it turns out this has been discussed, and the answer is Lazy loading react-router-dom, webpack not working. More specifically, in the webpack discussion here: Dynamic imports not generating separate chunks.

Ultimately the issue is that in the tsconfig, compilerOptions.module needs to be set to esnext.

I guess this is a duplicate, but I'll leave this here in case it helps anyone else in the future.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.