Server Island in Web : behind the 'land'


07 Aug 2024 / by KhanhIceTea

AstroJS has released new feature named "Server Island", it supports the static site can lazy-loading the non-interative
component (html part only).

So we can deep dive on how it works, is it a hype ?

I copied this code from the html source code (rendered) from their demo site https://server-islands.com

<div class="text-sm">
  <!--server-island-start-->
  <div class="text-sm text-center border border-transparent p-1 text-teal-300">
    <span class="space-x-0.5">
      <span class="inline-flex animate-[loading_1.4s_ease-in-out_infinite] rounded-full"></span>
      <span class="inline-flex animate-[loading_1.4s_ease-in-out_0.2s_infinite] rounded-full"></span>
      <span class="inline-flex animate-[loading_1.4s_ease-in-out_0.4s_infinite] rounded-full"></span>
    </span>
  </div>
  <script async type="module" data-island-id="cf238ace-17fc-48e8-b76c-5483f7ddf2e6">
    let componentId = "RoomAvailability";
    let componentExport = "default";
    let script = document.querySelector('script[data-island-id="cf238ace-17fc-48e8-b76c-5483f7ddf2e6"]');
    let data = {
      componentExport,
      props: {},
      slots: {},
    };

    let response = await fetch("/_server-islands/RoomAvailability", {
      method: "POST",
      body: JSON.stringify(data),
    });

    if (response.status === 200 && response.headers.get("content-type") === "text/html") {
      let html = await response.text();

      // Swap!
      while (script.previousSibling?.nodeType !== 8 && script.previousSibling?.data !== "server-island-start") {
        script.previousSibling?.remove();
      }
      script.previousSibling?.remove();

      let frag = document.createRange().createContextualFragment(html);
      script.before(frag);
    }
    script.remove();
  </script>
</div>

Ok, let dive in:

  1. The root div .text-sm is the main container element, which include all the content of "Server-Island" Component
  2. The first child div inside the root div is the fallback slot (mean it shows the placeholder when the we first loading the page, it's static and can be cached)
  3. The next async script which has data-island-id attribute as a way to track is self, later in script we see the script variable query it-self
  4. When the page is fully load, the script is called (because the script type=module)
  5. It fetch a route, put the info of the server component (including export name, props and slots)
  6. When the fetch request is success, the script then remove all the node before the script (while previousSibling), not the marked comment
  7. Then it add the returned html content to before the script (inside the root div)
  8. The script remove it-self after all!

;) So basically, Server-Island is easy!

Ref :


Sound good ?