tabler / tabler-icons

A set of over 5700 free MIT-licensed high-quality SVG icons for you to use in your web projects.
https://tabler.io/icons
MIT License
18.26k stars 914 forks source link

Slow experience in SvelteKit #518

Open MrAmericanMike opened 1 year ago

MrAmericanMike commented 1 year ago

I wonder if I'm doing something wrong, but I noticed that page reload is really slow while using @tabler/icons-svelte

I created a repo with the bare minimum example to reproduce the behavior. It's a SvelteKit project using my own starting template in which I add @tabler/icons-svelte and then each page that has some icon on it becomes really slow to refresh.

https://github.com/MrAmericanMike/svelte-tabler-icons-test The readme in this repo has a simple explanation also.

Not sure what the issue could be, I am using @tabler/icons-svelte in a different project that runs as an electron app and haven't noticed this behavior. The differences with that project are many, but I will try to do some experiments. (My first suspect was pnpm but using npm is the same. I'll try to experiment with different versions)

Well anyway I report it here in case anyone wants to take a look or have a clue as to what may be going on.

MrAmericanMike commented 1 year ago

Ok after some testing and looking for differences among my projects I noticed that having:

export const ssr = true;

in the +layout.js file causes the slow behavior (I need that set to true so @sveltejs/adapter-static can generate a fully static site)

Modifying the value to

export const ssr = false;

makes everything work faster.

I guess that's a workaround as for now, but at the same time not ideal.

Is this something I should report on SvelteKit instead?

Thanks in advance.

ostadomid commented 1 year ago

I had & still have the same problem with the last deprecated and current version.

rubenvar commented 1 year ago

I am having the same problem using @tabler/icons-svelte in a SvelteKit project. This happens in dev mode when there is at least one icon in a page.

First time I navigate or refresh a page, it taks ages to load:

13:32:40 [vite-plugin-svelte] prebundle libraries in progress ...
13:34:08 [vite-plugin-svelte] prebundle libraries done.
package     files     time     avg
admin-ui     3412   50.86s  14.9ms
13:34:08 [vite] ✨ new dependencies optimized: @tabler/icons-svelte

If I remove the icon in that page, restart the process and go to that page again, the load time goes back to normal:

13:36:13 [vite-plugin-svelte] ssr compile in progress ...
13:36:19 [vite-plugin-svelte] ssr compile done.
package     files    time      avg
admin-ui       23   0.77s   33.6ms
matmoxam commented 1 year ago

Also experiencing this issue. I thought prebundleSvelteLibraries being enabled by default would have solved this issue but doesn't seem to be the case.

bryanmylee commented 1 year ago

It's a little annoying, but importing the icon .svelte file directly resolves all these issues.

// Instead of
import {IconCheck} from '@tabler/icons-svelte';
// use
import IconCheck from '@tabler/icons-svelte/dist/svelte/icons/IconCheck.svelte';

Still haven't figured out how to fix the types though.

chjlsch commented 1 year ago

I think its a bug in vite. I had the same issue with a icon library for solidjs, where it built all icons, even if i only import one. When i do a release build of my sveltekit app, vite builds all >3000 tabler-icons too.

...
transforming (3354) node_modules/@tabler/icons-svelte/dist/svelte/icons/IconWeight.svelte
...
raulfdm commented 1 year ago

Not only Sveltekit but any Vite-related project.

I have a project using Astro + svelte, and a package that uses Vite + tabler icons react, and both have the same issue.

I think that's due to the nature of the import itself:

import { IconSomething } from '@tabler/icons-svelte'
                                    ^ "AKA import the whole thing"
MrAmericanMike commented 1 year ago

Not only Sveltekit but any Vite-related project.

I have a project using Astro + svelte, and a package that uses Vite + tabler icons react, and both have the same issue.

I think that's due to the nature of the import itself:

import { IconSomething } from '@tabler/icons-svelte'
                                    ^ "AKA import the whole thing"

I though that is what the destructuring part was supposed to do so when we do import { IconSomething } Using the curly braces is what tells the (compiler?) that we are only importing that specific icon and not the whole library. (At least that's how I though things work)

raulfdm commented 1 year ago

I though that is what the destructuring part was supposed to do so when we do import { IconSomething } Using the curly braces is what tells the (compiler?) that we are only importing that specific icon and not the whole library. (At least that's how I though things work)

It's an indication indeed, but it'll depends on how the bundle is created and how vite (in this case), understands and parse it.

I'll try this weekend to run this repository locally and do some experiments but tweaking the rollup configuration, switching to vite, instead and see if it gets any better. Otherwise I'll ask Vite's community some help to see if there's any extra configuration we could do to enable this behaviour.

As @bryanmylee said, the best workaround for now is import the icons from absolute path. By doing this, the compiler knows for sure that only that small bit should be included (and its dependencies).

radubl commented 1 year ago

+1 here.

We are also encountering the same slowness (due to vite rebuilding the entire set of icons on every page reload) when importing via import { IconX } from '@tabler/icons-svelte'. Switching all of our imports to import IconX from '@tabler/icons-svelte/dist/svelte/icons/IconX.svelte' avoids this issue, but we're keen to find a better solution.

raulfdm commented 1 year ago

Hey @codecalm 👋

Do you mind if I do a PoC with some changes on how you're bundling the files? 🤔

My idea is:

My idea isn't to impose any tech but demo how the package bundling process would look in an attempt to fix that problem.

Let me know what you think 😄

codecalm commented 1 year ago

for me it's okay, but @SyntaxJoker working on new build process in #556

@SyntaxJoker look at this ideas from @radubl

SyntaxJoker commented 1 year ago

In the new build process we will change how the bundle is generated, it should resolve this issue

raulfdm commented 1 year ago

In the new build process we will change how the bundle is generated, it should resolve this issue

Amazing... really looking forward to it! 🙌

gabrielnvian commented 1 year ago

@SyntaxJoker do you have any idea on how long the new build process will take to roll out?

Ebuka636 commented 1 year ago

This log appears to be from a Vite build process that is using the vite-plugin-svelte plugin.

The log shows that the plugin is pre-bundling libraries, which takes approximately 1 minute and 28 seconds to complete. After pre-bundling the libraries, the build process optimizes a new dependency called @tabler/icons-svelte.

The package admin-ui has 3412 files, and it takes approximately 50.86 seconds to process each file, with an average processing time of 14.9 milliseconds per file.

Overall, it seems like the build process is successful, and the dependencies are optimized.

RealSocius commented 1 year ago

Any updates on this? I am using the deep import in a project and while it works I am not happy with this.

PudottaPommin commented 1 year ago

Hello @codecalm ,

do you have any information about state of this?

anatoliy-t7 commented 1 year ago

I couldn't wait for it. Moved to https://github.com/antfu/unplugin-icons

gooodev commented 1 year ago

I found a temporary solution to the slow experience in dev mode. It works by rewriting the entry files internally using the plugin "vite-plugin-entry-shaking". I used the following vite.config.ts

import { sveltekit } from '@sveltejs/kit/vite';
import { defineConfig } from 'vite';
import EntryShakingPlugin from 'vite-plugin-entry-shaking';

export default defineConfig({
    plugins: [
        sveltekit(),
        await EntryShakingPlugin({
            targets: ['@tabler/icons-svelte'],
            extensions: ['svelte'],
        })
    ]
});
raulfdm commented 1 year ago

Hey @codecalm 👋

Do you mind if I do a PoC with some changes on how you're bundling the files? 🤔

My idea is:

  • switch from Rollup to vite, which has a very rich ecosystem and uses Rollup under the hood;
  • changing how the bundle is generated (e.g. single file to multiple files);
  • change from jest to vitest. This is a bit out, but once we have vite in place, we need 0 extra dependencies (such as babel, babel jest, whatever) to run the tests.

My idea isn't to impose any tech but demo how the package bundling process would look in an attempt to fix that problem.

Let me know what you think 😄

@codecalm I was tracking this issue, and it seems @SyntaxJoker can't finish it... maybe they're busy with something else.

Are you up to my previous proposal? I think I have the bandwidth to enhance the building process and attempt to solve this.

MrVauxs commented 1 year ago

Adding to the discussion. I love the ease of use of this module but the minute-long packaging times really are a nuisance. Let alone the extremely long dev reloads, but @gooodev's solution worked perfectly, so at least that's patched.

taythebot commented 1 year ago

Instead of changing the build process, you could create a preprocessor like Carbon design did for their icons. Essentially the preprocessor would replace the imports with direct ones.

Example: https://github.com/carbon-design-system/carbon-preprocess-svelte/blob/main/src/preprocessors/optimize-imports.ts

YummYume commented 1 year ago

I really hope this will get fixed sooner or later because this is in my opinion the best icon library to use with SvelteKit. It has pretty much everything you could need and works very well with TypeScript/VSCode auto import. I am using https://github.com/antfu/unplugin-icons as well in the meantime, as the solution proposed by @gooodev does not seem to work at all for me

raulfdm commented 8 months ago

I think worth mentioning that this problem seems to be related only to the @tabler/icons-svelte package in conjunction with a Vite setup and not necessarily bound to SveteltKit, but Vite + @tabler/icons-svelte.

To test this, you can do the following:

  1. create a vite - react project
  2. add @tabler/icons-react
  3. Named import an icon to the main page
  4. run build

You'll see the build is relatively fast, and in the final bundle, it included only the Icon we've imported.

Now if you do this with Svelte:

  1. create a vite - svelte project
  2. add @tabler/icons-svelte
  3. Named import an icon to the main page
  4. run build

The build will take longer, and all icons will be included in the final bundle.

stephane-klein commented 2 months ago

I couldn't wait for it. Moved to https://github.com/antfu/unplugin-icons

👍️

I migrated to unplugin-icons, good experience and no more performance issues 🙂.

deleonjulio commented 1 month ago

I have the same experience with @tabler/icons-react. (Vite, React, Tailwind and Mantine) It took 7 seconds to load my table when I'm using an icon.

I'm using the Icon like this.

              <Menu.Dropdown>
                <Menu.Item
                  color="red"
                  leftSection={<IconTrash style={{ width: rem(14), height: rem(14) }} />}
                >
                  Delete Item
                </Menu.Item>
              </Menu.Dropdown>

I removed the icon

          <Menu.Dropdown>
                <Menu.Item
                  color="red"
                >
                  Delete Item
                </Menu.Item>
              </Menu.Dropdown>

It loads really fast.