The idea of "islands architecture" was first coined by Etsy's frontend architect Katie Sylor-Miller in 2019, and expanded on in this post by Preact creator Jason Miller.
This kind of architecture is aim to solve the problem of the hydration need of MPA, which is deeply analyzed before.
As the name suggests, we can image the whole page as a sea of static, and the interactive parts as islands.As the following picture shows:
Then the hydration process will only be executed on the islands, which will make the first page load performance and TTI(time to interactive) better because it only needs partial client script that is correspond to the interactive parts.
The implementation of this architecture includes three parts: server runtime
、build time
and client runtime
.
Before introducing the architecture implementation, I think it is necessary to introduce how to use an island component.In island.js, the usage is very simple, just like the following code:
import { Aside } from './Aside.tsx';
export function Layout() {
return <Aside __island />;
}
You only need to add a __island
prop to the component when you use it, and then the component will automatically be identified as an island component. Island.js will only inject the client script of island components as well as their props when they are rendered on the client.
1. Server runtime.The server runtime is responsible for the server-side rendering of the islands, and it is also the core of the islands architecture. The main task of the server runtime is to collect the islands information in renderToString
process.
In Island.js
, it hijack the react/jsx-runtime's jsx function and collect the islands information when __island
prop is found in the component.
2. Build time. The build time is responsible for generating the client script of the islands and injecting it into the html. In build time, Island.js will generate three bundle:
window
object.Island.js will combine all island components into a virtual module and bundle them. In the virtual module, all of the island components will be hang on window
object. So in client hydration bundle, we can get the island components from window
object and hydrate them separately.
3. Client runtime. The client runtime is responsible for hydrating the islands in browser to make them interactive.
There are the some relevant code in repository:
island-jsx-runtime.js: The jsx runtime will collect the islands information when __island
prop is found in the component, served as the server runtime.
babel-plugin-island: The babel plugin will transform the __island
prop to __island=${islandAbsoluteFilePath}
prop, so in build time, bundler will find the island component file path.
SSGBuilder: The complete build time implement.
client-entry: The client runtime will hydrate the islands in browser to make them interactive.