preline icon indicating copy to clipboard operation
preline copied to clipboard

Some questions about tree-shaking

Open Ercilan opened this issue 4 months ago • 1 comments

First, the main issue is that all the top-level code such as addEventListener and window.$hsThemeSwitchCollection should be moved inside the block if (typeof window !== "undefined") { ... }. Otherwise, the conditional branches below are meaningless.

https://github.com/htmlstreamofficial/preline/blob/b44656ea345e7ebd1cdad8213234a7382b276aa6/src/plugins/theme-switch/index.ts#L240-L260


Next is the tree-shaking problem. After fixing the first issue, it becomes possible in Nuxt (SSR) to import only the required components, for example: import { HSOverlay } from "preline"; instead of import "preline/dist"; which imports the pre-bundled file that includes all components.

(Under normal circumstances, source code should be not imported in our project directly?)

I tested this locally: by importing only the required components, my final bundle size was reduced by over 100KB (for me).

Image

However, in the generated code, all components are still imported (this might still need to be addressed), though some code is gone—perhaps it was optimized? The component I need is performing normally in testing.

It would be great if you could provide an official example for on-demand imports / tree-shaking. Importing just 7 components adds ~350KB of JS, which is too large.

I know there are separate packages, but as far as I understand, preline’s JS library is mainly plugins and standalone classes, which should be tree-shakable? I hope to receive some answers and suggestions from you.

Ercilan avatar Sep 13 '25 08:09 Ercilan

I'm also trying to implement tree shaking to avoid serving unnecessary plugin. I'm using Preline v2 in Next.js and instead of doing

import('preline/preline').then(({ HSStaticMethods }) => {
   HSStaticMethods.autoInit();
});

I'm doing this which seems to work ok:

Promise.all([
  import('preline/dist/accordion'),
  import('preline/dist/collapse'),
  import('preline/dist/dropdown'),
]).then(([{ default: HSAccordion }, { default: HSCollapse }, { default: HSDropdown }]) => {
  HSAccordion.autoInit();
  HSCollapse.autoInit();
  HSDropdown.autoInit();
});

I also tried this

import('preline/preline').then(({ HSAccordion, HSCollapse, HSDropdown }) => {
  HSAccordion.autoInit();
  HSCollapse.autoInit();
  HSDropdown.autoInit();
});

But that still included the other plugins in the bundle which gave an error from HSOverlay

MangoMarcus avatar Oct 06 '25 14:10 MangoMarcus