What is a component anyway?
I previously said web components are not components, so it’s only fair that I expand on my idea of a component.
At the most basic level, a CSS class can be considered a component. It’s an intuitive way to reuse common styles in multiple places. Bootstrap is a very popular demonstration of this idea working at scale.
More commonly, components provide us a way to structure our markup, starting from the smallest pieces (an
<Icon> component, used within a
<Button>) and potentially building all the way up to the entire
<Page>. At each level, the component “hides” the underlying markup, whether that’s DOM elements or attributes. Crucially, the components must be “composable” for this to work; smaller components must be able to fit into bigger ones. You’ve probably heard the Lego blocks analogy used to describe this idea.
Modern frameworks like Svelte and Vue perfectly fit the definition so far. With their “single file components”, we can neatly define all related HTML/CSS/JS in one place.
For a concrete example, let’s use Svelte to create a Banner component that accepts text in a slot and contains a close button which will hide the banner.
And the usage feels familiar too. Assuming the file is imported as
Banner, we can use it like a regular HTML tag and populate the slot:
In the end, it will look something like this (the demo might not show up in your RSS reader, sorry).
Many frameworks have started offering “server components” that allow writing backend and frontend code in the same file. This lets us do things like reading from our database/filesystem and populating the markup immediately afterwards. This idea itself might not seem new (PHP has been doing this since the beginning), but the implementation certainly is. Examples include React Server Components, Fresh, and Astro.
Let’s look at Astro. Since it supports Svelte, we can take our Banner component from above and put it in an Astro component. We can decide what string to show inside the banner based on some backend API call. And we can also add any additional markup and scoped styles.
Now that’s a component!