lucide-icons / lucide

Beautiful & consistent icon toolkit made by the community. Open-source project and a fork of Feather Icons.
https://lucide.dev
ISC License
11.67k stars 540 forks source link

lucide-svelte bundling all 1221 icons #1475

Closed cheetahbyte closed 1 year ago

cheetahbyte commented 1 year ago

I wanted to bring up something that has been on my mind for a little while, when I import an icon from lucide-svelte and build my sveltekit project, all 1221 icons are directly bundled with it. This results in build times of about 30 seconds (on my machine).

To be honest, I am not sure if this can be considered a "bug".

The workaround I found is to import the file directly from it's "source".

Step to reproduce

+page.svelte

<script lang="ts">
import {UserIcon} from "lucide-svelte"
</script>

<UserIcon/>

inside your terminal

$ npm run build

Workaround

+page.svelte

<script lang="ts">
  import UserIcon from "lucide-svelte/dist/svelte/icons/user.svelte"
</script>

<UserIcon/>

inside your terminal

$ npm run build

Resources

Without Workaround

image image

With Workaround

image image

JanTrichter commented 1 year ago

After looking around for a bit and asking a few people this is the wanted behaviour so your assumption that this may not be a bug is correct.

Your provided solution is correct and here is a suggestion: Create an alias so you don't have to write the full path when importing the icons: svelte.config.js:

const config = {
    kit: {
        adapter: adapter(),
        alias: {
            $lucide: 'node_modules/lucide-svelte/dist/svelte/icons'
        }
    }
};

and then reference this in your component (don't forget run npm run dev again):

<script lang="ts">
  import Skull from '$lucide/skull.svelte';
</script>

<Skull />

Hope this helps. @ericfennis I assume this issue can be closed now.

cheetahbyte commented 1 year ago

I'm just wondering if bad performance (which is caused by this feature) is actually "wanted behaviour". But thanks for your help and answer, @JanTrichter.

JanTrichter commented 1 year ago

@cheetahbyte this should only take a bit longer during build time. The runtime performance should not be influenced by this.

DreamTexX commented 1 year ago

This issue may does not harm runtime performance, but build performance, which is an important factor. Think about pipelines and ci/cd (like github actions). When you deploy your app to something like vercel or other tools, this "a bit longer" build times can cost real money, that could be saved simply by designing this lib better than it currently is.

I think, I and many others would consider building unnecessary stuff (like unused icons) bad design. And the workaround mentioned here simply is a workaround that should not be common practise or a valid solution to this issue.

I would like to mention https://github.com/lucide-icons/lucide/issues/1403 which does seem to suffer from the same issue and demonstrates why this definitly is an issue and should be addressed.

zFl4wless commented 1 year ago

I agree with @DreamTexX

jguddas commented 1 year ago

@DreamTexX PRs or suggestions how to fix this are absolutely welcome, maybe the real money motivates someone 😄

ericfennis commented 1 year ago

I want to clarify the confusion that all icons are bundled when an application is built. That's not, but all icons are "transformed" during build, this because the library ships Svelte component files.

To be clear lucide-svelte is completely tree-shakable. Here a screenshot of a visualizer of a project with one imported icon.

image

however, @DreamTexX is right. The problem that we encounter is all the way how Svelte components are transpiled/transformed in Vite. If it sees an ".svelte" extension the Vite will transform this first to JS before it starts the tree-shaking process. That results in unnecessary transpilation and transformation. This something Vite and Svelte could improve, see issue https://github.com/vitejs/vite/issues/8237

So the solution for this can be pre-transforming Svelte components, shipping JS modules instead of Svelte components. This is something that we did before. But this led to some issues in SvelteKit see #833, this is because SvelteKit uses different preprocessing for client-side and SSR, and the pre-transformed lucide icons didn't work in SSR. So we switched to Svelte components instead. There is a possibility that since we had this issue with SvelteKit, the Svelte team solved it in the latest versions of the Svelte Preprocessor (the transformer of the Svelte files). So this is something we can check en test.

I've also looked at other frameworks and libraries but everyone is doing it differently. So not sure what the "way" is of shipping a Svelte component library: Pre-transformed or Svelte Components.

Would be nice if a Svelte expert can give me some info on this!

DreamTexX commented 1 year ago

What if the API is changed slightly to import icons from lucide-svelte/<IconName> (if this is possible somehow) instead of a single big index file?

JanTrichter commented 1 year ago

@DreamTexX See the first answer which is basically doing this.

DreamTexX commented 1 year ago

The first answer still is a kind of hacky workaround, i talk about using official ways like using this feature: https://kit.svelte.dev/docs/packaging#anatomy-of-a-package-json-exports

"exports": {
  "./SomeIcon.svelte": {
    "svelte": "path/to/icons/SomeIcon.svelte"
  }
}

This would have to be generated obviously. But this is just a suggestion based of some googeling.

ericfennis commented 1 year ago

@DreamTexX Yeah this maybe a good in-between solution to keep performance. I will work on this!

moritzhertler commented 1 year ago

This is still happening in my case with 0.275.0-beta.0. I'm not sure if I'm using the imports correctly (see my comment on #1284). Using the workaround proposed by @cheetahbyte does not work with versions later than 0.263.0 in sveltekit.

benbucksch commented 1 year ago

After #1499, the path to directly import icons is:

  import VideoIcon from 'lucide-svelte/icons/video'

This works for me and avoids the excessively slow compile. (Of course, replace Video/video with the name of the icon you need.)

This should now be listed in the README as the recommended way, and import { VideoIcon } from 'lucide-svelte' should be warned against in the README.

danawoodman commented 11 months ago

hate to +1 one this guy, but the fact I'm seeing 7mb+ of icons in my development app when I'm using 10 icons is harshing my vibes

i get there are probably reasons for this, but slowing down my dev process so I can use some SVGs is kinda frustrating

it does seem Tabler also has this issue, so i guess Lucide is not alone:

https://github.com/tabler/tabler-icons/issues/669

EDIT: unless I'm crazy, shouldn't you not be using barrel files?

image