0

Using route-based code splitting causes css duplicate in chunks.

Steps to reproduce:

  1. Create simple app with create-react-app
  2. Use react-router-dom for client side routing
  3. Add one common component with local css.
  4. Add 2 pages, using the common component with style overwriting
  5. Run build command
  6. Check static folder
// /components/CommonPageHeader/CommonPageHeader.module.scss
.header {
  color: black;
}
// /components/CommonPageHeader/CommonPageHeader.tsx
import styles from "./CommonPageHeader.module.scss";
import { ReactNode } from "react";

export const CommonPageHeader = (props: {
  className: string;
  children: ReactNode;`your text`
}) => {
  const { className = "", children } = props;

  return <h1 className={`${styles.header} ${className}`}>{children}</h1>;
};
// /pages/Home/Home.module.scss
.greenHeader {
  color: green;
}
// /pages/Home/Home.tsx
import React from "react";
import { Link } from "react-router-dom";
import { CommonPageHeader } from "../../components/CommonPageHeader/CommonPageHeader";
import styles from "./Home.module.scss";

const Home = () => (
  <>
    <CommonPageHeader className={styles.greenHeader}>
      I'm a green header
    </CommonPageHeader>
    <Link to={"some-page"}>Some page</Link>
  </>
);
export default Home;

// /pages/SomePage/SomePage.module.scss
.redHeader {
  color: red;
}
// /pages/SomePage/SomePage.tsx
import React from "react";
import { Link } from "react-router-dom";
import { CommonPageHeader } from "../../components/CommonPageHeader/CommonPageHeader";
import styles from "./SomePage.module.scss";

const SomePage = () => {
  return (
    <>
      <CommonPageHeader className={styles.redHeader}>
        I'm a red header
      </CommonPageHeader>
      <Link to={"/"}>Home</Link>
    </>
  );
};
export default SomePage;

// index.tsx

import React, { Suspense } from "react";
import ReactDOM from "react-dom/client";
import { createBrowserRouter, RouterProvider } from "react-router-dom";

const Home = React.lazy(() => import("./pages/Home/Home"));
const SomePage = React.lazy(() => import("./pages/SomePage/SomePage"));

const router = createBrowserRouter([
  {
    path: "/",
    element: (
      <Suspense>
        <Home />
      </Suspense>
    ),
  },
  {
    path: "/some-page",
    element: (
      <Suspense>
        <SomePage />
      </Suspense>
    ),
  },
]);

const root = ReactDOM.createRoot(
  document.getElementById("root") as HTMLElement
);
root.render(
  <React.StrictMode>
    <RouterProvider router={router} />
  </React.StrictMode>
);

You get css chunks with duplicates and unexpected styles overwrites in production:

// /build/static/css/499.408c3ff0.chunk.css
.CommonPageHeader_header__eTauC {
    color: #000
}

.Home_greenHeader__YwF4H {
    color: green
}
// /build/static/css/136.855973ab.chunk.css
.CommonPageHeader_header__eTauC {
    color: #000
}

.SomePage_redHeader__a-I8c {
    color: red
}

Demo page

  1. Click to some page link
  2. Go back to home page

Repo

Is there way to prevent it?

5
  • Just spit-balling here, but I'm guessing this happens because each split chunk of code independently needs the "common" header CSS, so each get's a "copy" of it and there's no way to know ahead of time which will be fetched first. You might try importing the CommonPageHeader higher up in the React tree so it's included with a "core" app chunk, if that makes sense. I don't believe react-router has much of anything to do with this so I've retagged with hopefully more accurate tags for someone with more experience to see and provide an answer. Commented Oct 28, 2022 at 15:58
  • @drew-reese The issue take place only if you use react-router and React.lazy together. It works fine without React.lazy, as well as React.lazy works fine without react-router. Commented Oct 28, 2022 at 19:07
  • I see. Perhaps it's something to do with the new Data APIs just released with RRDv6.4. Does the issue reproduce if you use a more conventional RRD approach by using the useRoutes hook and pass the routes config to that and render within a regular BrowserRouter component? Or manually render the routes via the Routes and Route components? Commented Oct 28, 2022 at 19:13
  • @drew-reese The issue reproduces in all cases described by you. Commented Oct 29, 2022 at 8:17
  • Honestly I don't think this is an "issue", but rather by design with how code-splitting works generally. Commented Oct 30, 2022 at 18:15

0

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.