-
-
Notifications
You must be signed in to change notification settings - Fork 23
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 request] Generate SVG sprites as a build step #9
Comments
It's certainly a cool idea, for those needing to eke out better performance in this regard (though I doubt most users do, as a handful of icons, tree-shaken, is usually a few tens of kBs of JS -- you seem to be using quite a few!). Definitely something I considered when laying the groundwork for 1.0. My main misgiving is the high maintenance cost, and further fragmentation of what is already a pretty large number of libraries and ports I maintain. Build tooling is complicated -- you have highlighted just a few of the many wrinkles you'd encounter trying to make a Tailwind-like solution that "just works" for this use-case. I unfortunately don't have the time or bandwidth to maintain such a thing (things) right now. It seems like a perfect opportunity for an enterprising contributor, though! Orthogonal to this, I AM working on a font-stripping tool to generate minimal font+css bundles that can be statically built and included as public, cacheable assets: https://pack.phosphoricons.com. The tool is still in beta, and it unfortunately does not do any automagic at build time (you have to manually pick the icons you want), but still provides the exact ergonomics of using @phosphor-icons/web at dev time. |
A (probably stupid) alternative just came to me:
<PhosphorIcon name="cube" weight="fill" size={72} color="red" /> It's dumb. It might be really bad to create a new Document for each icon. But it works: https://stackblitz.com/edit/stackblitz-starters-ydxdwf?file=src%2FApp.tsx,src%2FPhosphor.tsx |
(Not sure if this is the right place for feature requests. Feel free to move it somewhere more appropriate)
Motivation
Performance (load times, rendering, memory)
This is a visualization of our current production app bundle (no worries! it's split into multiple chunks in case anyone gets dizzy). There's quite a bit going on. The biggest chunk of
node_modules/
is@phosphor-icons
which takes up ~300kb of JS, notably (the orange slice). This stems from us using@phosphor-icons/react
.Instead it would be beneficial if all of this could move over here, into the
assets/
part of the app, as a static*.svg
asset that can be cached by browsers and does not clutter JS bundles more than necessary.As Jason Miller points out correctly
Developer experience
Technically, this is possible today by downloading and using the individual
*.svg
files instead of relying on@phosphor-icons/react
. This comes with a significant decline in developer experience though, some of which is described nicely in The "best" way to manage icons in React.js<img />
cannot be styled using CSS<link rel="preload" />
, SVGs rendered as<img />
introduce request waterfalls for the initial load. Adding an appropriate preload tag for each icon gets tiring@phosphor-icons/react
's benefits such as easily importing any of the icons or changing the icon's weight via nothing more than a prop change becomes way more tediousThe blog's proposed solution is to render SVGs as a sprite
and reference them in a component (taking React as an example)
This solves both the performance problems as well as
1.
(can be styled with CSS) and2.
(only need to preload one file) but still requires manual work to update the SVG sprite by hand each time a new icon is added / the weight is changed / phosphor receives an update where icons are improved/changed.This can be improved partially by using remix-cli which provides a way to create an SVG sprite by pointing it at a folder containing individual
*.svg
files. But most of the above still holds true.Proposed solution
Putting together all of the above, it would be ideal to have a solution that
@phosphor-icons/react
with (partial?) support of all its featuresFor this to work, I propose new packages
@phosphor-icons/react-sprite
and@phosphor-icons/vue-sprite
that both offer a<PhosphorIcon />
much like the<Icon />
component above, offering an interface including all the IconProps& { name: "address-book" | "air-traffic-control" | ... }
.On top of that, there'll need to be a build process much like the one of TailwindCSS:
Read the contents of
*.[jsx, tsx, vue|
files, find all<PhosphorIcon />
s and evaluate their props. Based on that, generate asprite.svg
that can be imported in one place.Unfortunately this comes with a rather major caveat I believe: Just as the tailwind build process, this requires to only put static strings as props since otherwise this cannot be statically analyzed without going through the immense pain of somehow evaluating dynamic code. One alternative I can think of is to offer named components
<AddressBookThin />
,<AddressBookLight />
and the likes that under the hood all resolve to the same<PhosphorIcon />
for the sole purpose of being able to statically analyze the code for the build process. This still feels kinda meh but all things considered might still be worth it considering the upsides. There may be other ideas I haven't thought of of course.I understand that this is a passion project built in your guys' free time and something like this isn't done quickly. Just wanted to share some ideas! :)
The text was updated successfully, but these errors were encountered: