tabler / tabler-icons

A set of over 5200 free MIT-licensed high-quality SVG icons for you to use in your web projects.
https://tabler.io/icons
MIT License
17.57k stars 875 forks source link

NextJS13 build results in huge bundle size #793

Open oliverkidd opened 10 months ago

oliverkidd commented 10 months ago

At present, when shipping to production with tabler icons react (nextjs13) over 10mb of bundle space is allocated to the icons. It appears every import is importing the entire js library so the library grows larger than expected (see img) and that has issues with compilation time and so ttfb.

From my understand this comes down to issues with tree-shaking as outlined more extensive in other icon libraries: React Icons: https://github.com/react-icons/react-icons/pull/727 Mui icons: https://github.com/mui/material-ui/issues/35840

As far as my research has pointed this comes down to the inability to allow direct imports for an icon, eg:

import {UserIcon} from "@tabler/icons-react

should be available instead as something like:

import UserIcon from "@tabler/icons-react/dist/cjs/icons/UserIcon

This is the way icons are handler in Material UI etc and having tested their library they have no issue in this build size (although issues with tree shaking still exist for compilation speed)

Is there any work to rectify this? I can see similar comments from Jan this year. If not, it may be a move to material icons our end, which would be a shame as it'll be a mess to migrate!

Bundle breakdown of node.js IMG_1861

Details of size/source from tabler

Screenshot 2023-08-18 at 20 46 14
Elvincth commented 10 months ago

The same issue with Next.js 13 app dir, the huge bundle size causes out of memory error. It would be good if modularized import is available.

Elvincth commented 10 months ago

I have been able to slove this my adding a modularizeImports config in next.config.mjs, it reduce my runtime bundle size

import "./src/env.mjs";

/** @type {import("next").NextConfig} */
const config = {
  experimental: { serverActions: true },
  modularizeImports: {
    "@tabler/icons-react": {
      transform: "@tabler/icons-react/dist/esm/icons/{{member}}",
    },
  },
};
export default config;