Next.js Discord

Discord Forum

React-icons included in client bundle, How can I avoid this.

Unanswered
Korean bullhead posted this in #help-forum
Open in Discord
Avatar
Korean bullheadOP
So I have a bunch of weird requirements which is ending up in making my client bundle huge
I have this dynamic Icon component (attached)
Which is used like this:
export function BaseList<T extends BaseListItem>({ divIndex, items, boxText }: BaseListProps<T>) {
  return (
    <BorderBox texts={[{ textYPosition: "top", textXPosition: "left", text: boxText }]}>
      <ul className="w-full space-y-2">
        {items.map((item, itemIndex) => (
          <BaseListItemClient
            key={item.id || `list-item-${itemIndex}`}
            divIndex={divIndex}
            item={{
              ...item,
              rightContent:
                typeof item.rightContent !== "string" &&
                  item.rightContent !== null &&
                  "iconName" in item.rightContent ? (
                  <DynamicIcon
                    className="text-inherit"
                    icon={item.rightContent?.iconName.trim()}
                    iconFamily={item.rightContent?.iconFamily}
                  />
                ) : (
                  item.rightContent
                )
            }}
            itemIndex={itemIndex}
          />
        ))}
      </ul>
    </BorderBox>
  );
}
Image

2 Replies

Avatar
Korean bullheadOP
Now I have a parallel route:
import React from "react";

import { BlogList } from "@/components/Lists/BlogList";
import { getArchivedPosts, getPublishedPosts } from "@/components/Lists/BlogList/getPostsAction";

export const dynamic = "force-static"; 

export default async function Blog({
  searchParams
}: {
  searchParams: Promise<{ status: "published" | "archived" }>;
}) {
  const status = (await searchParams).status;
  const initialItems = status === "archived" ? await getArchivedPosts() : await getPublishedPosts();
  return <BlogList initialItems={initialItems} />;
}

where BlogList is this:
"use client";

import { useSearchParams } from "next/navigation";
import { useEffect, useState } from "react";

import { BaseList } from "@/components/Lists/BaseList";

import { getArchivedPosts, getPublishedPosts } from "./getPostsAction";

export function BlogList({ initialItems }) {
  const searchParams = useSearchParams();
  const [items, setItems] = useState(initialItems);
  const status = (
    ["published", "archived"].includes(searchParams.get("status") || "")
      ? searchParams.get("status")!
      : "published"
  ) as "published" | "archived";

  useEffect(() => {
    if (status === "archived") getArchivedPosts().then(setItems);
    if (status === "published") getPublishedPosts().then(setItems);
  }, [status]);

  return (
    <BaseList
      divIndex={2}
      items={items}
      boxText={status === "archived" ? "blog - [archived]" : "blog"}
    />
  );
}


I have to keep the parallel route as force-static since the actual base route /blog/page.tsx needs to be static and I can't have mixed dynamic status where the parallel route is dynamic and base route is static.

Now since BlogList is a client component, BaseList gets bundled to client code which further includes DynamicIcon
This causes the client bundle to be bloated with react-icons...

Can someone suggest me a workaround for this problem?