Astro 4.12 is out now! This release includes the first experimental release of Server Islands, our new solution to integrate high performance static HTML and dynamic server-generated components together. Improvements to pagination and syntax highlighting are also included.
This release includes the following highlights:
- Experimental: Server Islands
- Added
first
andlast
URLs to pagination data - Added support for the Shiki’s
defaultColor
option - New
inferRemoteSize
function
To upgrade an existing project, use the automated @astrojs/upgrade
CLI tool. Alternatively, upgrade manually by running the upgrade command for your package manager:
# Recommended:npx @astrojs/upgrade
# Manual:npm install astro@latestpnpm upgrade astro --latestyarn upgrade astro --latest
Experimental: Server Islands
In 2021 Astro brought the idea of islands architecture to the mainstream, allowing you to create “islands” of interactive client-side components while most of your page is generated statically.
With Server islands we are extending this same architecture to the server. Server islands make it easy to combine high performance static HTML and dynamic server-generated components.
Within any given web page you might have content that is:
- Completely static and never changes.
- Dynamically backed by a database that changes infrequently, but more often than you deploy.
- Personalized content, tailored to individual users.
Currently, you must choose one caching strategy for all of these types of content, and if the page is a logged-in experience that usually means no caching at all. Now, with Server islands you get the best of both worlds.
Server islands are used for your most dynamic content; personalized content like a user’s avatar, their shopping cart, and product reviews. When these components are deferred, you’re free to more aggressively cache the page itself.
This means that users, logged in or not, will see the most critical parts of the page instantly, as they are caching on Edge CDNs. Fallback content will be visible for a short amount of time before the dynamic islands are then loaded.
Each island is loaded independent from the rest; this means a slower island, such as one connected to a legacy backend, won’t delay the rest of personalized content from being seen and interacted with.
Performance
To test the viability of this idea we built server-islands.com. This demo is inspired by the Next.js Partial Prerendering demo, reskinned to suit Astro’s personality. Server Islands has a lot in common with Partial Prerendering (PPR), especially in its goal of allowing increased cacheability of pages.
Metrics | partialprerendering.com | server-islands.com |
---|---|---|
TTFBTime To First Byte | 0.838s | 0.766s |
FCPFirst Contentful Paint | 1.740s | 1.251s |
LCPLargest Contentful Paint | 1.740s | 1.405s |
TBTTotal Blocking Time | 0.093s | 0.018s |
Source | WebPageTest | WebPageTest |
server-islands.com performs consistently faster in repeated runs; it scores a 20% faster Largest Contentful Paint, which is one of Google’s 3 Core Web Vitals impacting both user experience and SEO.
Instead of starting the request to the origin on the server like PPR, Server Islands do so from the browser. This means that while Server islands paint earlier, they might finish later than PPR.
Both Server islands and PPR work best in sites like these, where the main page content can be edge cached. They work well for ecommerce but would probably not be something you want to use for a social network feed. Due to the page being edge cached, that wait for the island request is minimal.
Ultimately, we are confident in this tradeoff as being the best overall performance for Astro users across both the user experience and passing Core Web Vitals without requiring any special backend infrastructure or support to get started.
Portability
We built Server islands with portability in mind. It doesn’t depend on any server infrastructure so it will work with any host you have, from a Node.js server in a Docker container to the serverless provider of your choice.
Our implementation happens mostly at build-time, where component content is swapped out for a small script, one that can almost fit into a Tweet.
Each of the islands marked with server:defer
are split off into their own special route which the script fetches at run time. The trade-off is that the island doesn’t get a head-start rendering as it might if it depended on edge handling, but we think the performance numbers favor the simpler approach we’ve taken thus far.
Trying out Server Islands
We’re still working on polishing the feature, but you can try out Astro Server Islands today by enabling the feature in Astro 4.12:
import { defineConfig } from 'astro/config';import netlify from '@astrojs/netlify';
export default defineConfig({ output: 'hybrid', adapter: netlify(),
experimental: { serverIslands: true, },})
Server islands, as the name implies, run on the server, so you’ll need to use either 'server'
or 'hybrid'
output. Once you’ve enabled the feature you can use them on any component using the server:defer
directive:
<Avatar server:defer> <GenericUserImage slot="fallback" /></Avatar>
When Astro builds your site it will omit the component and inject a script in its place, in addition to the content you’ve marked with slot="fallback"
. When the page loads in the browser, these components along with any props you pass to them, will be requested to a special endpoint that renders them and returns the HTML.
Server Islands are normal Astro components and can use any of the features you expect from Astro like middleware, slots, client:
islands.
Getting involved
Server Islands have an active RFC. We’re still finalizing the details and features; we’ll likely be adding encrypted props for example. Try out the release in 4.12 and let us know what you think.
Added first
and last
URLs to pagination data
The paginate() helper now returns the first
and last
properties in the pagination data. These properties contain the first and last page urls, respectively. Thanks to @tsawada for contributing this feature!
Added support for the Shiki’s defaultColor
option
The defaultColor
option allows you to override the values of a theme’s inline style, adding only CSS variables to give you more flexibility in applying multiple color themes. This option can be configured in your Shiki config to apply throughout your site, or passed to Astro’s built-in <Code>
component to style an individual code block. Thank you to @madcampos for contributing this!
New inferRemoteSize
function
In Astro 4.4, we added a new property to the Image and Picture components and getImage()
to automatically infer the size of remote images. Thanks to @itsmatteomanf, this release now includes a new function, inferRemoteSize()
, that allows you to get the size of a remote image indendently of these components or getImage()
.
This can be useful if you’re using the image width to generate different densities, or if you need the image dimension for styling purposes.
---import { inferRemoteSize, Image } from 'astro:assets';
const { width, height } = await inferRemoteSize('https://...');---
<Image src={"https://..."} width={width / 2} height={height} densities={[1.5, 2]} />
Some more things
As we do, Astro 4.12 includes more bug fixes and smaller improvements that couldn’t make it into this post! Check out the full release notes to learn more.
Special thanks to @sarah11918, @Fryuni, @ARipeAppleByYoursTruly and everyone else who contributed to this release.