Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature]: Tree Shaking with only one primitive #449

Closed
2 tasks
madebyfabian opened this issue Oct 11, 2023 · 12 comments
Closed
2 tasks

[Feature]: Tree Shaking with only one primitive #449

madebyfabian opened this issue Oct 11, 2023 · 12 comments

Comments

@madebyfabian
Copy link
Contributor

madebyfabian commented Oct 11, 2023

Describe the feature

I just discovered that radix-vue is adding 50kb to my build. I am only using the Dialog though, nothing else.
Bildschirmfoto 2023-10-11 um 10 09 11

It would be great for performance if there was a way to actively tree-shake it, something like

import { DialogClose, DialogContent, /* ... */ } from 'radix-vue/dialog'

because it's hard for me to imagine that only the Dialog primitive taking up more than 50kb.

Additional information

  • I intend to submit a PR for this feature.
  • I have already implemented and/or tested this feature.
@madebyfabian
Copy link
Contributor Author

Even larger in the server build:
Bildschirmfoto 2023-10-11 um 10 21 46

@k11q
Copy link
Member

k11q commented Oct 11, 2023

I fully support the idea 👍

@sadeghbarati
Copy link
Collaborator

sadeghbarati commented Oct 11, 2023

Semi-related #443

Also, it's preferred not to use UMD for cjs build, cause this format is too old and tree-shaking will not work correctly


Vite config example
https://github.com/freddy38510/vue3-lazy-hydration/blob/master/vite.config.ts

@zernonia
Copy link
Member

@madebyfabian how was your setup yaa? You are using Radix-vue's Nuxt modules?
I also had this idea of preservedModules when compiling it. 😁

@madebyfabian
Copy link
Contributor Author

@zernonia I am using it with the latest nuxt 3.7.4. I did not add it as a nuxt module. I just tried out adding it, it's the exact same outcome.

If it helps, I can create a reproduction repositiory.

@zernonia
Copy link
Member

did a quick test with Nuxt3 playground locally.. using preservedModules and it seems to be the same.. Seems like the tree-shaking is working fine.

image

However with settings @floating-ui as external, it is much smaller size.

image

@madebyfabian
Copy link
Contributor Author

@zernonia So you mean the current stats (52kb client, 82kb server) are already the tree-shaked version? Is there a way to shrink it down? Background is: I want to fit my nuxt nitro build inside a edge function, where 1MB is the size limit.

I installed headlessui/vue and replaced my modal to use the Dialog from headlessui to compare the size. Their currently at 25kb client, 0kb server. And I am not sure if they even do tree shaking.

If the tree shaking is already working and that's the minimum size to get to, then I think I can close this ticket.

@zernonia
Copy link
Member

zernonia commented Oct 11, 2023

There's still some room for improvement . We can push it down to 36kb after extracting @floating-ui. #443

You sure headless-ui is serving 0kb in server? 😮

@madebyfabian
Copy link
Contributor Author

@zernonia Yes as far as I can tell. This is my implementation:

Vue Component
<template>
   <div class="lg:hidden">
      <button
         @click="isOpen = true"
         aria-label="Menü öffnen"
         class="rounded-full bg-primary-700/10 flex items-center justify-center w-9 h-9">
         <NuxtIcon name="menu" class="text-gray-500 text-xl" />
      </button>
      <Dialog :open="isOpen" @close="isOpen = false">
         <DialogPanel class="fixed bg-primary-700 text-white p-6 focus:outline-none z-30 inset-0 w-full h-full">
            <DialogTitle class="hidden">Menü</DialogTitle>
            <div class="flex justify-end">
               <button
                  @click="isOpen = false"
                  class="rounded-full bg-white/10 flex items-center justify-center w-9 h-9">
                  <NuxtIcon name="close" class="text-white text-xl" />
               </button>
            </div>
            <slot />
         </DialogPanel>
      </Dialog>
   </div>
</template>
<script setup lang="ts">
   import { Dialog, DialogPanel, DialogTitle } from '@headlessui/vue'
   
   const route = useRoute()
   
   const isOpen = ref(false)
   
   // Close when user navigates
   watch(
    () => route.fullPath,
    () => {
     isOpen.value = false
    }
   )
</script>

And it results in 0kb Server Side. But it causes a hydration mismatch, forcing me to wrap it inside <ClientOnly>. But the 0kb result is with or without the <ClientOnly>. So to be fair, I think radix-vue is ssr friendlier.

@zernonia
Copy link
Member

Icic.. thanks for the insight @madebyfabian !

hmmm I wonder how to achieve 0kb server bundling tho.. you have any idea how this can be achieve? 🤔

@madebyfabian
Copy link
Contributor Author

@zernonia I would love to assist on this! Currently I don't have an idea 😄

@zernonia
Copy link
Member

Will close this off yaa @madebyfabian as Tree-shaking is working correctly. But I will keep this in mind and we can look into how headless/ui bundle with 0kb server side in other ticket 😁

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants