vercel / next.js

The React Framework
https://nextjs.org
MIT License
122.63k stars 26.25k forks source link

Icon component with dynamic svg imports vs bundle size #67247

Open pepew-le-boss opened 3 days ago

pepew-le-boss commented 3 days ago

Link to the code that reproduces this issue

https://github.com/pepew-le-boss/dynamic-icons-nextjs

To Reproduce

  1. read the readme.md
  2. read the content of the page.tsx and modify it according to the directions
  3. build the app
  4. look at the bundle size

Current vs. Expected behavior

When importing a single svg, it should not import all the svgs, making the bundle size huge.

Provide environment information

Operating System:
  Platform: win32
  Arch: x64
  Version: Windows 10 Enterprise
  Available memory (MB): 14274
  Available CPU cores: 8
Binaries:
  Node: 18.17.0
  npm: N/A
  Yarn: N/A
  pnpm: N/A
Relevant Packages:
  next: 14.2.3 // There is a newer version (14.2.4) available, upgrade recommended!
  eslint-config-next: 14.2.3
  react: 18.3.1
  react-dom: 18.3.1
  typescript: 5.4.5
Next.js Config:
  output: N/A
 ⚠ There is a newer version (14.2.4) available, upgrade recommended!
   Please try the latest canary version (`npm install next@canary`) to confirm the issue still exists before creating a new issue.
   Read more - https://nextjs.org/docs/messages/opening-an-issue

Which area(s) are affected? (Select all that apply)

create-next-app, Lazy Loading, Performance, Webpack

Which stage(s) are affected? (Select all that apply)

next build (local)

Additional context

I'm trying to create an Icon component that imports svgs dynamically (without blowing up the bundle size).

I've gathered all the potential solutions we can find on the web, like require.context(), dynamic(), await import(), etc. but all of them are making the bundle size huge. Only one of them does not do that but it involves loading the svgs client side, meaning that the svgs appear on the page after a delay.

I don't get why when importing a single svg, all the svg are imported. NextJS should separate them into chunks.

I've set a repo with all the different solutions: https://github.com/pepew-le-boss/dynamic-icons-nextjs