withastro / astro

The web framework for content-driven websites. ⭐️ Star to support our work!
https://astro.build
Other
46.79k stars 2.49k forks source link

💡 RFC: Builtin Icon Support #1374

Closed FredKSchott closed 3 years ago

FredKSchott commented 3 years ago

Background & Motivation

Proposed Solution

---
import {Icon} from 'astro/components';
---
<div>
  <Icon collection="fa-solid" icon="rocket" />
  <Icon collection="fa-solid" icon="rocket" scale={4} color={'red'} />
</div>

Detailed Design

The Icon component works by fetching the SVG data via iconify (internally, this just gets the SVG data from a big internal JSON object). SVG is returned as the component body.

Limitations

Tradeoffs

Two important tradeoff callouts:

1. Using an <Icon> component vs. ESM imports

One nice thing about https://github.com/antfu/unplugin-icons is that every icon gets imported via ESM import, so that it's really clear to both users and tooling which icons are used. For example, when you use ESM imports you could scan your entire project ahead-of-time to find out which icons were used (more on why this matters in the next section).

We could ditch the <Icon> idea and just add something like unplugin-icons directly to our build pipeline, so that you'd do this instead:

- import {Icon} from 'astro/components';
+ import RocketIcon from 'icon:fa-solid/rocket';

- <Icon collection="fa-solid" icon="rocket" /> 
+ <RocketIcon /> 

Another perk of this system is that this would give us a natural hook to serve local SVGs with a similar API support. The current proposal is an API for popular remote iconsets only.

import RocketIcon from 'icon:local/rocket.svg';
// or
import RocketIcon from '../icons/rocket.svg';

2. No SVG spritesheet support

This approach intentionally doesn't implement the idea of SVG spritesheets. When you use any <Icon> component, you don't know which icons your project is using until after the build has completed and the Icons have been rendered inline.

You could maybe do something clever, but this coincides with my own recent skepticism of the SVG spritesheet idea. Some quick reasons why I've cooled on this in favor of inline SVGs:

Inline SVGs are just so much more easy, lightweight, and less risky to get us stuck. I don't believe that this stops us from implementing a cool SVG spritesheet solution or something else in the future).

Open Questions

Help make it happen!

FredKSchott commented 3 years ago

I'd really love feedback on the Tradeoffs section, specifically comparing this proposal to an alternative design that leverages ESM imports instead of a dedicated Icon component.

eyelidlessness commented 3 years ago

(This isn't commentary on the proposal itself, but more generally about Astro's scope and priorities. But I think it's worth discussing in this context, and hopefully more broadly as well.)

I mean this in the most constructive way possible: I'm unclear on what Astro's scope is intended to be at this point. When it was first introduced, my impression was the scope is: component oriented framework-agnostic SSG[/SSR eventually] with partial hydration, with some special treats not typically available in those frameworks (eg Markdown component). Since then it's grown proposed to include quite a lot more than that.

Like, batteries included is/can be cool to a degree, it can help with many common use cases. This feels well beyond that to me?

One of the biggest challenges in the web space is mixing tooling to satisfy complex or specialized needs and use cases. The more opinionated and the larger the scope of any given piece of tooling, the less generally able it is to help mitigate that challenge. (Side note: this is a big part of why esbuild is doing so well in the bundler space, despite being feature-minimal and despite its lack of AST facilities being a deoptimization.)

I, personally, would rather see Astro focus on building helpful interfaces versus helpful features (apart from its core value proposition). By all means develop an icon solution if there's demand for it. But I'd rather see it as a more general plugin/build pipeline library than part of Astro main.

And... this is asking a lot from the community but I think there's precedent (renderer plugins, which I'm exceedingly proud to have helped influence) for defining that interface as a priority rather than defining the implementation or use case itself. If there's openness to this as a consideration as a stand-in for this RFC, I'd love to spend more of my brainpower on it even just to see things go in a more general and composable/interoperable direction.

FredKSchott commented 3 years ago

Good points. the idea of adding this as an external package and not built-in is noted. There’s actually nothing stopping this from being an external package today, so maybe we start there and then see how people like it.

I don’t think this is slippery slope situation. There are only a few situations that we’ve considered handling in core like this: images, icons, and fonts.

FredKSchott commented 3 years ago

I'm now +1 on starting this as an external package for now, and then revisiting as we prepare for v1.0. As the RFC shows, there's too many different ways to do Icons and we really haven't explored any of them yet in Astro. I'd rather leave exploration to user land before we consider what core support looks like.

Note that Image and Font support will almost certainly still be built into Astro core. Unlike Icons, these use-cases are much more straightforward, and too important to leave to some external package.

eyelidlessness commented 3 years ago

these use-cases are much more straightforward

They’re really very much not :(

and too important to leave to some external package

Even your apparent competitor in this space (Vercel/Next) is very minimal in their ambitions but more importantly very permissive about external packages.

FredKSchott commented 3 years ago

They are absolutely more straightforward than icons! Maybe you've had different experience from me, in which case I'd love some constructive feedback when we get to that work to make sure that we aren't missing anything obvious.

I'm not sure where you get the sense that we wouldn't support external packages, if something in this post gave you that impression please let me know.

jasikpark commented 3 years ago

I'm now +1 on starting this as an external package for now, and then revisiting as we prepare for v1.0. As the RFC shows, there's too many different ways to do Icons and we really haven't explored any of them yet in Astro. I'd rather leave exploration to user land before we consider what core support looks like.

Note that Image and Font support will almost certainly still be built into Astro core. Unlike Icons, these use-cases are much more straightforward, and too important to leave to some external package.

I'm definitely in favor of developing this as an external package.. I think there are at least a couple of features that would benefit the best from being fully sorted out in userspace as external packages unless it's truly necessary to be built by Astro.. then once there's a beloved leader package, it could be rolled into the Astro project if wanted.