Ark-ui imports all of the components in node-modules when I am only using a couple
cini9 opened this issue · comments
Description
I am using ark-ui in unison with panda-css and NextJS 14 to create styled components for my website. The package is working great except in terms of performances. Using the nextjs-bundle-analyzer I am trying to minimize the bundle size on the server and the client. When I check the bundle on the client side, I see that all of the ark-ui components are included even though I am only using the ark.svg and ark.a :
From the documentation, I expected tree shaking to exclude these components from the bundle :
I cannot import the two components that I use as path-based imports as mentionned in the second import method, so I am currently importing the whole of ark as follows:
Is there something I am missing to remove all of the unused components from my bundle ?
Thanks a lot !
Link to Reproduction (or Detailed Explanation)
See above description.
Steps to Reproduce
See description above.
Ark UI Version
1.3.0
Framework
- React
- Solid
- Vue
Browser
No response
Additional Information
No response
Thanks for taking your time to create this issue. Unfortunately the RSC bundler in Next.js is not capable of three shaking so you have to rely on path imports. I will add a note to the docs.
The ark
function can also imported as a path import like so: import { ark } from '@ark-ui/react/factory'
Source: https://park-ui.com/docs/panda/components/button#installation
Thanks for the reply ! Shame NextJs doesn't include tree shaking. Just out of curiosity, which bundlers are capable of tree-shaking ?
Almost all I know. Webpack, Vite but also the next.js bundler for client components. Just not the rsc one.
For reference vercel/next.js#62238
@cschroeter This is not true. I bring this up the last time. The exports of ark are simply wrong in the highest index file. The following works, verified locally it only pulls things in what is used. Please see the following comment. #2353 (comment)
This proposal does not work as you expect. For example an import of the DialogTrigger would look sth like this:
import { Dialog } from "@ark-ui/react"
<Dialog.DialogTrigger />
Or
<Dialog.Dialog.Trigger />
I hope it is clear why this is not a viable solution especially not since there is a path import available to use.
@cschroeter Can you please explain what is wrong by that? A clear path would be nice, right now the same thing is exported through various path / segments.
Avoid repetition, the naming like Dialog.DialogTrigger
is confusing, this even more Dialog.Dialog.Trigger
Trigger is part of Dialog, also at the implementation detail so using it differently without the component initiating the required react context will result in an error. To indicate such a thing the naming Dialog.Trigger
is more intuitive to understand. To do this move the renamed exports specified in dialog/dialog.tsx towards dialog/index.ts.
export { Backdrop, CloseTrigger, Content, Context, Description, Positioner, Root, Title, Trigger }
then go to the highest index.ts file and add export * as Dialog from './dialog'
, now you can use it like this. The result is also a bundle where only Dialog is included.
import { Dialog } from "@ark-ui/react"
<Dialog.Trigger />
Thx!
That is correct but then it is no longer possible to import a component part the "classical" way like
import { DialogTrigger } from '@ark-ui/react'
Developers only option is to use this Dialog.Trigger notation, which has poor syntax highlighting in Vue.js (Vetur) and will always bundle all parts of the dialog even though you are just using a few parts.
I will bring this up in the next meeting with @segunadebayo but I am not convinced especially not since there are already open PRs in Nextjs that would address this issue
@cschroeter Please reopen this or the other issue I have created, otherwise another one might be generated because more and more people see the problem and wonder.
Exporting every sub-component may be really error prone from a consumer perspective because the developer has to know the implementation detail of the Provider counterpart otherwise the result is an error.
To avoid these situations exports have to be limited, maybe by differentiating among mandatory and optional parts.
You are probably right with the bundle size when you are not interested in using e.g. Dialog.Trigger this might be optional, and should not be bundled when not used.
Other things should be made mandatory for those putting in behind the Dialog Namespace makes more sense.
I don’t have the answer to these problems, a more intuitive API would be much appreciated, especially with all the sub components at play.
Thx!
As far as I understand, the "custom" components can be exported like : import { Slider } from 'ark-ui/react/slider'. Which may help with tree-shaking and not having all of the components imported in the bundle. But I really couldn't find a way to import the "a" nor the "svg" components (which are the two that I use) in the same way as the Slider. Is this correct ?