Reputation: 10686
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?
Upvotes: 0
Views: 1154
Reputation: 10686
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.
Upvotes: 2