chakra-ui / ark

A headless library for building reusable, scalable design systems that works for a wide range of JS frameworks.

Home Page:https://ark-ui.com

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

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 :

Screenshot 2024-04-08 at 15 47 25

From the documentation, I expected tree shaking to exclude these components from the bundle :

Screenshot 2024-04-08 at 15 40 59

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:

Screenshot 2024-04-08 at 15 48 52

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

@cini9

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.

@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)

@gurkerl83

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 ?