Skip to content

Instantly share code, notes, and snippets.

@matthewp
Last active December 1, 2021 19:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save matthewp/f4b188b3fc4fe02a88ce9601bd96621b to your computer and use it in GitHub Desktop.
Save matthewp/f4b188b3fc4fe02a88ce9601bd96621b to your computer and use it in GitHub Desktop.
SSR discovery

Table of contents

Goals

  • Produce an SSR build that can be run without dependencies on Vite.
  • Use SSR build to power static-generation.
  • SSG should happen in a single-pass (no post-processing HTML after generation).
<!-- Global CSS -->
<link rel="stylesheet" href={Astro.resolve('../styles/theme.css')} />
<link rel="stylesheet" href={Astro.resolve('../styles/code.css')} />
<link rel="stylesheet" href={Astro.resolve('../styles/index.css')} />

Becomes:

<!-- Global CSS -->
<link
  rel="stylesheet"
  href="/src/styles/theme.css"
/>
<link
  rel="stylesheet"
  href="/src/styles/code.css"
/>
<link
  rel="stylesheet"
  href="/src/styles/index.css"
/>

Question

  • Should these be bundled?

Solution

  • Needs @component static solution.
  • Overload Astro.resolve when generating the HTML.
  • If bundling, the compiler needs to turn this into an expression of some sort, so that we can control if this gets rendered.
<style>
  .layout {
    display: grid;
    grid-auto-flow: column;
    grid-template-columns: 
      minmax(var(--gutter), 1fr) 
      minmax(0, var(--max-width)) 
      minmax(var(--gutter), 1fr);
    overflow-x: hidden;
  }
</style>
<style> /* ... */ </style>

Becomes:

<style astro-style="true">
  .layout.astro-4B45IKYD {
    display: grid;
    grid-auto-flow: column;
    grid-template-columns: minmax(var(--gutter), 1fr) minmax(
        0,
        var(--max-width)
      ) minmax(var(--gutter), 1fr);
    overflow-x: hidden;
  }
</style>
<style astro-style="true">
  header.astro-XSR2FY3G {
    z-index: 11;
    height: var(--theme-navbar-height);
    width: 100%;
    background-color: var(--theme-navbar-bg);
    display: flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
    position: sticky;
    top: 0;
  }
 </style>

Solution

  • These are rendered by $$result.styles
    • Add a $$result.links that gets passed in instead.
    • Some type of route configuration file maybe:
    {
      "/introduction": {
        "module": "dist/assets/introduction.hash.mjs",
        "links": [
          { "rel": "stylesheet": "href": "../assets/introduction.hash.css" }
        ]
      }
    }

This JSX (relevant for any framework component):

import './Search.css';

export default Search() {
  return <div class="search"> ... </div>
}

Does not get rendered

This relies on HTML post-processing and depends on the Vite module graph.

Solution

  • These CSS should be built out during vite.build.
  • They will be added via the route configuration.

This Astro usage:

<ThemeToggleButton client:visible />

Gets generated as:

<script
  type="module"
  data-astro-component-hydration
  astro-script="/en/introduction/script-2"
>
  import setup from "astro/client/visible.js";
  setup("Z23uxs3", { value: true }, async () => {
    const [{ default: Component }, { default: hydrate }] =
      await Promise.all([
        import(
          "/src/components/ThemeToggleButton.tsx"
        ),
        import("@astrojs/renderer-preact/client.js"),
      ]);
    return (el, children) =>
      hydrate(el)(
        Component,
        {
          class: "astro-WUQUYG3V",
        },
        children
      );
  });
</script>

Questions

  • Is client:visible allowed to be dynamic?

Problems

  • This relies on runtime to know that @astrojs/renderer-preact/client.js is used.
  • If client:visible is dynamic, relies on runtime to know that astro/client/visible.js is used.
  • Given that renderers are discovered at runtime, bundling these inline scripts head of time seems impossible. This is probably ok.

Solution

  • Make client:visible, etc static, so we know which are needed.
  • Create an entrypoint for astro/client/visible.js.
  • For each renderer listed in astroConfig.renderers, create an entrypoint. This will mean it's available if needed at runtime.
  • Create a mapping of directives to their final built file in the route configuration.
  • Create a mapping of renderers to their final built file in the route configuration.

This Astro:

<script type="module" src={Astro.resolve('./script.js')} hoist></script>

Gets generated as:

<script
  type="module"
  src="/src/components/script.js"
  hoist="true"
  astro-script="/en/introduction/script-0"
></script>

Solution

  • Needs a @component like solution to ensure static.
  • Make this part of the route configuration like with stylesheet links.

Astro:

<img src={Astro.resolve('../images/twitter.png')} />

Generates this HTML:

<img src="/src/images/twitter.png" class="astro-QY234LXS">

Solution

  • Needs the @component type of solution.

Astro:

<img srcset={`${Astro.resolve('../images/twitter.png')} 1x,
  ${Astro.resolve('../images/twitter@2x.png')} 2x,
  ${Astro.resolve('../images/twitter@3x.png')} 3x`} />

Generates this HTML:

<img srcset="/src/images/twitter.png 1x, /src/images/twitter@2x.png 2x, /src/images/twitter@3x.png 3x" class="astro-QY234LXS">

Solution

  • Needs the @component type of solution.

This Astro (or JSX):

---
import imgUrl from '../images/twitter.png';
---

<img src={imgUrl} />

Will render:

<img src="/src/images/twitter.png" class="astro-QY234LXS">

Solution

We should be able to make this be hashed and included in dist. This way we don't need to make any changes to the template.

Generated HTML example

<html dir="ltr" lang="en-us" class="initial astro-2FQHPSSZ">
  <head>
    <!-- Global Metadata -->
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width" />

    <link rel="icon" type="image/svg+xml" href="/favicon.svg" />
    <link rel="alternate icon" type="image/x-icon" href="/favicon.ico" />

    <link rel="sitemap" href="/sitemap.xml" />

    <!-- Global CSS -->
    <link
      rel="stylesheet"
      href="/Users/matthew/dev/astro/examples/docs/dist/styles/theme.css"
    />
    <link
      rel="stylesheet"
      href="/Users/matthew/dev/astro/examples/docs/dist/styles/code.css"
    />
    <link
      rel="stylesheet"
      href="/Users/matthew/dev/astro/examples/docs/dist/styles/index.css"
    />

    <!-- Preload Fonts -->
    <link rel="preconnect" href="https://fonts.googleapis.com" />
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
    <link
      href="https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:ital@0;1&display=swap"
      rel="stylesheet"
    />

    <!-- Scrollable a11y code helper -->
    <script type="module" src="/make-scrollable-code-focusable.js"></script>

    <!-- This is intentionally inlined to avoid FOUC -->
    <script>
      const root = document.documentElement;
      const theme = localStorage.getItem("theme");
      if (
        theme === "dark" ||
        (!theme && window.matchMedia("(prefers-color-scheme: dark)").matches)
      ) {
        root.classList.add("theme-dark");
      } else {
        root.classList.remove("theme-dark");
      }
    </script>

    <!-- Global site tag (gtag.js) - Google Analytics -->
    <!-- <script async src="https://www.googletagmanager.com/gtag/js?id=G-TEL60V1WM9"></script>
<script>
  window.dataLayer = window.dataLayer || [];
  function gtag(){dataLayer.push(arguments);}
  gtag('js', new Date());
  gtag('config', 'G-TEL60V1WM9');
</script> -->
    <!-- Page Metadata -->
    <link rel="canonical" href="http://localhost:3000/en/introduction/" />

    <!-- OpenGraph Tags -->
    <meta
      property="og:title"
      content="Introduction 🚀 Your Documentation Website"
    />
    <meta property="og:type" content="article" />
    <meta property="og:url" content="http://localhost:3000/en/introduction/" />
    <meta property="og:locale" content="en_US" />
    <meta
      property="og:image"
      content="https://github.com/withastro/astro/blob/main/assets/social/banner.jpg?raw=true"
    />
    <meta
      property="og:image:alt"
      content="astro logo on a starry expanse of space, with a purple saturn-like planet floating in the right foreground"
    />
    <meta name="description" property="og:description" content="Docs intro" />
    <meta property="og:site_name" content="Your Documentation Website" />

    <!-- Twitter Tags -->
    <meta name="twitter:card" content="summary_large_image" />
    <meta name="twitter:site" content="astrodotbuild" />
    <meta
      name="twitter:title"
      content="Introduction 🚀 Your Documentation Website"
    />
    <meta name="twitter:description" content="Docs intro" />
    <meta
      name="twitter:image"
      content="https://github.com/withastro/astro/blob/main/assets/social/banner.jpg?raw=true"
    />
    <meta
      name="twitter:image:alt"
      content="astro logo on a starry expanse of space, with a purple saturn-like planet floating in the right foreground"
    />

    <!--
  TODO: Add json+ld data, maybe https://schema.org/APIReference makes sense?
  Docs: https://developers.google.com/search/docs/advanced/structured-data/intro-structured-data
  https://www.npmjs.com/package/schema-dts seems like a great resource for implementing this.
  Even better, there's a React component that integrates with `schema-dts`: https://github.com/google/react-schemaorg
-->

    <title>Introduction 🚀 Your Documentation Website</title>

    <style astro-style="true">
      body {
        width: 100%;
        display: grid;
        grid-template-rows: var(--theme-navbar-height) 1fr;
        --gutter: 0.5rem;
        --doc-padding: 2rem;
      }
      .layout.astro-2FQHPSSZ {
        display: grid;
        grid-auto-flow: column;
        grid-template-columns: minmax(var(--gutter), 1fr) minmax(
            0,
            var(--max-width)
          ) minmax(var(--gutter), 1fr);
        overflow-x: hidden;
      }
      .layout.astro-2FQHPSSZ > * {
        width: 100%;
        height: 100%;
      }
      .grid-sidebar.astro-2FQHPSSZ {
        height: 100vh;
        position: sticky;
        top: 0;
        padding: 0;
      }
      #grid-left.astro-2FQHPSSZ {
        position: fixed;
        background-color: var(--theme-bg);
        z-index: 10;
        display: none;
      }
      #grid-main.astro-2FQHPSSZ {
        padding: var(--doc-padding) var(--gutter);
        grid-column: 2;
        display: flex;
        flex-direction: column;
        height: 100%;
      }
      #grid-right.astro-2FQHPSSZ {
        display: none;
      }
      .mobile-sidebar-toggle {
        overflow: hidden;
      }
      .mobile-sidebar-toggle #grid-left.astro-2FQHPSSZ {
        display: block;
        top: 2rem;
      }
      @media (min-width: 50em) {
        .layout.astro-2FQHPSSZ {
          overflow: initial;
          grid-template-columns: 20rem minmax(0, var(--max-width));
          gap: 1em;
        }
        #grid-left.astro-2FQHPSSZ {
          display: flex;
          padding-left: 2rem;
          position: sticky;
          grid-column: 1;
        }
      }
      @media (min-width: 72em) {
        .layout.astro-2FQHPSSZ {
          grid-template-columns: 20rem minmax(0, var(--max-width)) 18rem;
          padding-left: 0;
          padding-right: 0;
          margin: 0 auto;
        }
        #grid-right.astro-2FQHPSSZ {
          grid-column: 3;
          display: flex;
        }
      }
    </style>
    <style astro-style="true">
      header.astro-XSR2FY3G {
        z-index: 11;
        height: var(--theme-navbar-height);
        width: 100%;
        background-color: var(--theme-navbar-bg);
        display: flex;
        align-items: center;
        justify-content: center;
        overflow: hidden;
        position: sticky;
        top: 0;
      }
      .logo.astro-XSR2FY3G {
        display: flex;
        overflow: hidden;
        width: 30px;
        font-size: 2rem;
        flex-shrink: 0;
        font-weight: 600;
        line-height: 1;
        color: hsla(var(--color-base-white), 100%, 1);
        gap: 0.25em;
        z-index: -1;
      }
      .logo.astro-XSR2FY3G a.astro-XSR2FY3G {
        padding: 0.5em 0.25em;
        margin: -0.5em -0.25em;
        text-decoration: none;
        font-weight: bold;
      }
      .logo.astro-XSR2FY3G a.astro-XSR2FY3G {
        transition: color 100ms ease-out;
        color: var(--theme-text);
      }
      .logo.astro-XSR2FY3G a.astro-XSR2FY3G:hover,
      .logo.astro-XSR2FY3G a.astro-XSR2FY3G:focus {
        color: var(--theme-text-accent);
      }
      .logo.astro-XSR2FY3G h1.astro-XSR2FY3G {
        font: inherit;
        color: inherit;
        margin: 0;
      }
      .nav-wrapper.astro-XSR2FY3G {
        display: flex;
        align-items: center;
        justify-content: flex-end;
        gap: 1em;
        width: 100%;
        max-width: 82em;
        padding: 0 1rem;
      }
      @media (min-width: 50em) {
        header.astro-XSR2FY3G {
          position: static;
          padding: 2rem 0rem;
        }
        .logo.astro-XSR2FY3G {
          width: auto;
          margin: 0;
          z-index: 0;
        }
        .menu-toggle.astro-XSR2FY3G {
          display: none;
        }
        .logo.astro-XSR2FY3G {
          width: auto;
        }
      } /** Style Algolia */
      :root {
        --docsearch-primary-color: var(--theme-accent);
        --docsearch-logo-color: var(--theme-text);
      }
      .search-item.astro-XSR2FY3G {
        display: none;
        position: relative;
        z-index: 10;
        flex-grow: 1;
        padding-right: 0.7rem;
        display: flex;
        max-width: 200px;
      }
      .search-item > * {
        flex-grow: 1;
      }
      @media (min-width: 50em) {
        .search-item.astro-XSR2FY3G {
          max-width: 400px;
        }
      }
    </style>
    <style astro-style="true">
      nav.astro-D2RGYUBV {
        width: 100%;
        margin-right: 1rem;
      }
      .nav-groups.astro-D2RGYUBV {
        height: 100%;
        padding: 2rem 0;
        overflow-x: visible;
        overflow-y: auto;
        max-height: 100vh;
      }
      .nav-groups.astro-D2RGYUBV > li.astro-D2RGYUBV + li.astro-D2RGYUBV {
        margin-top: 2rem;
      }
      .nav-groups.astro-D2RGYUBV > :first-child {
        padding-top: var(--doc-padding);
      }
      .nav-groups.astro-D2RGYUBV > :last-child {
        padding-bottom: 2rem;
        margin-bottom: var(--theme-navbar-height);
      }
      .nav-group-title.astro-D2RGYUBV {
        font-size: 1rem;
        font-weight: 700;
        padding: 0.1rem 1rem;
        text-transform: uppercase;
        margin-bottom: 0.5rem;
      }
      .nav-link.astro-D2RGYUBV a.astro-D2RGYUBV {
        font-size: 1rem;
        margin: 1px;
        padding: 0.3rem 1rem;
        font: inherit;
        color: inherit;
        text-decoration: none;
        display: block;
      }
      .nav-link.astro-D2RGYUBV a.astro-D2RGYUBV:hover,
      .nav-link.astro-D2RGYUBV a.astro-D2RGYUBV:focus {
        background-color: var(--theme-bg-hover);
      }
      .nav-link.astro-D2RGYUBV a.astro-D2RGYUBV[aria-current="page"] {
        color: var(--theme-text-accent);
        background-color: var(--theme-bg-accent);
        font-weight: 600;
      }
      :root.theme-dark
        .nav-link.astro-D2RGYUBV
        a.astro-D2RGYUBV[aria-current="page"] {
        color: hsla(var(--color-base-white), 100%, 1);
      }
      @media (min-width: 50em) {
        .nav-groups.astro-D2RGYUBV {
          padding: 0;
        }
      }
    </style>
    <style astro-style="true">
      .sidebar-nav.astro-V33CJSJK {
        width: 100%;
        position: sticky;
        top: 0;
      }
      .sidebar-nav-inner.astro-V33CJSJK {
        height: 100%;
        padding: 0;
        padding-top: var(--doc-padding);
        overflow: auto;
      }
    </style>
    <style astro-style="true">
      .skiplink.astro-YQDGESHS,
      .skiplink.astro-YQDGESHS:focus,
      .skiplink.astro-YQDGESHS:focus-visible {
        position: absolute;
        padding: 0.25em;
        font-size: larger;
        top: 0;
        left: 0;
        right: 0;
        z-index: 9;
        display: block;
        text-align: center;
        background-color: var(--theme-text-accent);
        color: var(--theme-bg);
        border-radius: 0.25em;
        outline: var(--theme-bg) solid 1px;
        outline-offset: 0;
      }
    </style>
    <style astro-style="true">
      .edit-on-github.astro-WUQUYG3V {
        text-decoration: none;
        font: inherit;
        color: inherit;
        font-size: 1rem;
      }
    </style>
    <style astro-style="true">
      .content.astro-RRP3EK7S {
        padding: 0;
        max-width: 75ch;
        width: 100%;
        height: 100%;
        display: flex;
        flex-direction: column;
      }
      .content.astro-RRP3EK7S > section.astro-RRP3EK7S {
        margin-bottom: 4rem;
      }
      .block.astro-RRP3EK7S {
        display: block;
      }
      @media (min-width: 50em) {
        .sm\:hidden.astro-RRP3EK7S {
          display: none;
        }
      }
    </style>
    <style astro-style="true">
      astro-root,
      astro-fragment {
        display: contents;
      }
    </style>
    <script
      type="module"
      src="/Users/matthew/dev/astro/examples/docs/dist/assets/script.js"
      hoist="true"
      astro-script="/en/introduction/script-0"
    ></script>
    <script
      type="module"
      data-astro-component-hydration
      astro-script="/en/introduction/script-1"
    >
      import setup from "astro/client/idle.js";
      setup("Z1eEE1d", { value: true }, async () => {
        const [{ default: Component }, { default: hydrate }] =
          await Promise.all([
            import(
              "/Users/matthew/dev/astro/examples/docs/dist/assets/SidebarToggle.tsx"
            ),
            import("@astrojs/renderer-preact/client.js"),
          ]);
        return (el, children) =>
          hydrate(el)(
            Component,
            {
              class: "astro-XSR2FY3G",
            },
            children
          );
      });
    </script>
    <script
      type="module"
      data-astro-component-hydration
      astro-script="/en/introduction/script-2"
    >
      import setup from "astro/client/media.js";
      setup("Z2roRX7", { value: "(min-width: 50em)" }, async () => {
        const [{ default: Component }, { default: hydrate }] =
          await Promise.all([
            import(
              "/Users/matthew/dev/astro/examples/docs/dist/assets/TableOfContents.tsx"
            ),
            import("@astrojs/renderer-preact/client.js"),
          ]);
        return (el, children) =>
          hydrate(el)(
            Component,
            {
              headers: [
                {
                  depth: 2,
                  slug: "getting-started",
                  text: "Getting Started",
                },
              ],
              class: "astro-V33CJSJK",
            },
            children
          );
      });
    </script>
    <script
      type="module"
      data-astro-component-hydration
      astro-script="/en/introduction/script-3"
    >
      import setup from "astro/client/visible.js";
      setup("Z23uxs3", { value: true }, async () => {
        const [{ default: Component }, { default: hydrate }] =
          await Promise.all([
            import(
              "/Users/matthew/dev/astro/examples/docs/dist/assets/ThemeToggleButton.tsx"
            ),
            import("@astrojs/renderer-preact/client.js"),
          ]);
        return (el, children) =>
          hydrate(el)(
            Component,
            {
              class: "astro-WUQUYG3V",
            },
            children
          );
      });
    </script>
    <script
      type="module"
      data-astro-component-hydration
      astro-script="/en/introduction/script-4"
    >
      import setup from "astro/client/media.js";
      setup("45Vad", { value: "(max-width: 50em)" }, async () => {
        const [{ default: Component }, { default: hydrate }] =
          await Promise.all([
            import(
              "/Users/matthew/dev/astro/examples/docs/dist/RightSidebar/TableOfContents.tsx"
            ),
            import("@astrojs/renderer-preact/client.js"),
          ]);
        return (el, children) =>
          hydrate(el)(
            Component,
            {
              headers: [
                {
                  depth: 2,
                  slug: "getting-started",
                  text: "Getting Started",
                },
              ],
              class: "astro-RRP3EK7S",
            },
            children
          );
      });
    </script>
  </head>

  <body>
    <header class="astro-XSR2FY3G">
      <a href="#article" class="sr-only skiplink astro-YQDGESHS"
        ><span class="astro-YQDGESHS">Skip to Content</span></a
      >

      <nav class="nav-wrapper astro-XSR2FY3G" title="Top Navigation">
        <div class="menu-toggle astro-XSR2FY3G">
          <astro-root uid="Z1eEE1d"
            ><button type="button" aria-pressed="false" id="menu-toggle">
              <svg
                xmlns="http://www.w3.org/2000/svg"
                width="1em"
                height="1em"
                fill="none"
                viewBox="0 0 24 24"
                stroke="currentColor"
              >
                <path
                  stroke-linecap="round"
                  stroke-linejoin="round"
                  stroke-width="2"
                  d="M4 6h16M4 12h16M4 18h16"
                ></path></svg
              ><span class="sr-only">Toggle sidebar</span>
            </button></astro-root
          >
        </div>
        <div class="logo flex astro-XSR2FY3G">
          <svg
            class="logo"
            width="40"
            height="40"
            viewBox="0 0 256 256"
            fill="none"
            xmlns="http://www.w3.org/2000/svg"
          >
            <style>
              #flame {
                fill: var(--theme-text-accent);
              }
              #a {
                fill: var(--theme-text-accent);
              }
            </style>
            <title>Logo</title>
            <path
              id="a"
              fill-rule="evenodd"
              clip-rule="evenodd"
              d="M163.008 18.929c1.944 2.413 2.935 5.67 4.917 12.181l43.309 142.27a180.277 180.277 0 00-51.778-17.53l-28.198-95.29a3.67 3.67 0 00-7.042.01l-27.857 95.232a180.225 180.225 0 00-52.01 17.557l43.52-142.281c1.99-6.502 2.983-9.752 4.927-12.16a15.999 15.999 0 016.484-4.798c2.872-1.154 6.271-1.154 13.07-1.154h31.085c6.807 0 10.211 0 13.086 1.157a16.004 16.004 0 016.487 4.806z"
            ></path>
            <path
              id="flame"
              fill-rule="evenodd"
              clip-rule="evenodd"
              d="M168.19 180.151c-7.139 6.105-21.39 10.268-37.804 10.268-20.147 0-37.033-6.272-41.513-14.707-1.602 4.835-1.961 10.367-1.961 13.902 0 0-1.056 17.355 11.015 29.426 0-6.268 5.081-11.349 11.349-11.349 10.743 0 10.731 9.373 10.721 16.977v.679c0 11.542 7.054 21.436 17.086 25.606a23.27 23.27 0 01-2.339-10.2c0-11.008 6.463-15.107 13.974-19.87 5.976-3.79 12.616-8.001 17.192-16.449a31.024 31.024 0 003.743-14.82c0-3.299-.513-6.479-1.463-9.463z"
            ></path>
          </svg>
          <a href="/" class="astro-XSR2FY3G">
            <h1 class="astro-XSR2FY3G">Documentation</h1>
          </a>
        </div>
        <div style="flex-grow: 1" class="astro-XSR2FY3G"></div>
      </nav>
    </header>
    <main class="layout astro-2FQHPSSZ">
      <aside
        id="grid-left"
        class="grid-sidebar astro-2FQHPSSZ"
        title="Site Navigation"
      >
        <nav aria-labelledby="grid-left" class="astro-D2RGYUBV">
          <ul class="nav-groups astro-D2RGYUBV">
            <li class="astro-D2RGYUBV">
              <div class="nav-group astro-D2RGYUBV">
                <h2 class="nav-group-title astro-D2RGYUBV"></h2>
                <ul class="astro-D2RGYUBV"></ul>
              </div>
            </li>
            <li class="astro-D2RGYUBV">
              <div class="nav-group astro-D2RGYUBV">
                <h2 class="nav-group-title astro-D2RGYUBV">Section Header</h2>
                <ul class="astro-D2RGYUBV">
                  <li class="nav-link astro-D2RGYUBV">
                    <a
                      href="/en/introduction"
                      aria-current="page"
                      class="astro-D2RGYUBV"
                      >Introduction</a
                    >
                  </li>
                  <li class="nav-link astro-D2RGYUBV">
                    <a
                      href="/en/page-2"
                      aria-current="false"
                      class="astro-D2RGYUBV"
                      >Page 2</a
                    >
                  </li>
                  <li class="nav-link astro-D2RGYUBV">
                    <a
                      href="/en/page-3"
                      aria-current="false"
                      class="astro-D2RGYUBV"
                      >Page 3</a
                    >
                  </li>
                </ul>
              </div>
            </li>
            <li class="astro-D2RGYUBV">
              <div class="nav-group astro-D2RGYUBV">
                <h2 class="nav-group-title astro-D2RGYUBV">Another Section</h2>
                <ul class="astro-D2RGYUBV">
                  <li class="nav-link astro-D2RGYUBV">
                    <a
                      href="/en/page-4"
                      aria-current="false"
                      class="astro-D2RGYUBV"
                      >Page 4</a
                    >
                  </li>
                </ul>
              </div>
            </li>
          </ul>
        </nav>

        <script>
          window.addEventListener("DOMContentLoaded", (event) => {
            var target = document.querySelector('[aria-current="page"]');
            if (target && target.offsetTop > window.innerHeight - 100) {
              document.querySelector(".nav-groups").scrollTop =
                target.offsetTop;
            }
          });
        </script>
      </aside>
      <div id="grid-main" class="astro-2FQHPSSZ">
        <article id="article" class="content astro-RRP3EK7S">
          <section class="main-section astro-RRP3EK7S">
            <h1 class="content-title astro-RRP3EK7S" id="overview">
              Introduction
            </h1>
            <nav class="block sm:hidden astro-RRP3EK7S">
              <astro-root uid="45Vad"
                ><h2 class="heading">On this page</h2>
                <ul>
                  <li class="header-link depth-2">
                    <a href="#overview">Overview</a>
                  </li>
                  <li class="header-link depth-2">
                    <a href="#getting-started">Getting Started</a>
                  </li>
                </ul></astro-root
              >
            </nav>
            <p><strong>Welcome to Astro!</strong></p>
            <p>
              This is the <code data-astro-raw>docs</code> starter template. It
              contains all of the features that you need to build a
              Markdown-powered documentation site, including:
            </p>
            <ul>
              <li><strong>Full Markdown support</strong></li>
              <li><strong>Responsive mobile-friendly design</strong></li>
              <li><strong>Sidebar navigation</strong></li>
              <li><strong>Search (powered by Algolia)</strong></li>
              <li><strong>Multi-language i18n</strong></li>
              <li><strong>Automatic table of contents</strong></li>
              <li><strong>Automatic list of contributors</strong></li>
              <li>✅ (and, best of all) <strong>dark mode</strong></li>
            </ul>
            <h2 id="getting-started">Getting Started</h2>
            <p>
              To get started with this theme, check out the
              <code data-astro-raw>README.md</code> in your new project
              directory. It provides documentation on how to use and customize
              this template for your own project. Keep the README around so that
              you can always refer back to it as you build.
            </p>
            <p>
              Found a missing feature that you can’t live without? Please
              suggest it on Discord
              <a href="https://astro.build/chat"
                >(#ideas-and-suggestions channel)</a
              >
              and even consider adding it yourself on GitHub! Astro is an open
              source project and contributions from developers like you are how
              we grow!
            </p>
            <p>Good luck out there, Astronaut. 🧑‍🚀</p>
          </section>
          <nav class="block sm:hidden astro-RRP3EK7S">
            <ul class="astro-WUQUYG3V"></ul>
            <div
              style="margin: 2rem 0; text-align: center"
              class="astro-WUQUYG3V"
            >
              <astro-root uid="Z23uxs3"
                ><div class="theme-toggle">
                  <label class
                    ><svg
                      xmlns="http://www.w3.org/2000/svg"
                      width="20"
                      height="20"
                      viewBox="0 0 20 20"
                      fill="currentColor"
                    >
                      <path
                        fillRule="evenodd"
                        d="M10 2a1 1 0 011 1v1a1 1 0 11-2 0V3a1 1 0 011-1zm4 8a4 4 0 11-8 0 4 4 0 018 0zm-.464 4.95l.707.707a1 1 0 001.414-1.414l-.707-.707a1 1 0 00-1.414 1.414zm2.12-10.607a1 1 0 010 1.414l-.706.707a1 1 0 11-1.414-1.414l.707-.707a1 1 0 011.414 0zM17 11a1 1 0 100-2h-1a1 1 0 100 2h1zm-7 4a1 1 0 011 1v1a1 1 0 11-2 0v-1a1 1 0 011-1zM5.05 6.464A1 1 0 106.465 5.05l-.708-.707a1 1 0 00-1.414 1.414l.707.707zm1.414 8.486l-.707.707a1 1 0 01-1.414-1.414l.707-.707a1 1 0 011.414 1.414zM4 11a1 1 0 100-2H3a1 1 0 000 2h1z"
                        clipRule="evenodd"
                      ></path></svg
                    ><input
                      type="radio"
                      name="theme-toggle"
                      value="light"
                      title="Use light theme"
                      aria-label="Use light theme" /></label
                  ><label class
                    ><svg
                      xmlns="http://www.w3.org/2000/svg"
                      width="20"
                      height="20"
                      viewBox="0 0 20 20"
                      fill="currentColor"
                    >
                      <path
                        d="M17.293 13.293A8 8 0 016.707 2.707a8.001 8.001 0 1010.586 10.586z"
                      ></path></svg
                    ><input
                      type="radio"
                      name="theme-toggle"
                      value="dark"
                      title="Use dark theme"
                      aria-label="Use dark theme"
                  /></label></div
              ></astro-root>
            </div>
          </nav>
        </article>
      </div>
      <aside
        id="grid-right"
        class="grid-sidebar astro-2FQHPSSZ"
        title="Table of Contents"
      >
        <nav class="sidebar-nav astro-V33CJSJK" aria-labelledby="grid-right">
          <div class="sidebar-nav-inner astro-V33CJSJK">
            <astro-root uid="Z2roRX7"
              ><h2 class="heading">On this page</h2>
              <ul>
                <li class="header-link depth-2">
                  <a href="#overview">Overview</a>
                </li>
                <li class="header-link depth-2">
                  <a href="#getting-started">Getting Started</a>
                </li>
              </ul></astro-root
            >

            <ul class="astro-WUQUYG3V"></ul>
            <div
              style="margin: 2rem 0; text-align: center"
              class="astro-WUQUYG3V"
            >
              <astro-root uid="Z23uxs3"
                ><div class="theme-toggle">
                  <label class
                    ><svg
                      xmlns="http://www.w3.org/2000/svg"
                      width="20"
                      height="20"
                      viewBox="0 0 20 20"
                      fill="currentColor"
                    >
                      <path
                        fillRule="evenodd"
                        d="M10 2a1 1 0 011 1v1a1 1 0 11-2 0V3a1 1 0 011-1zm4 8a4 4 0 11-8 0 4 4 0 018 0zm-.464 4.95l.707.707a1 1 0 001.414-1.414l-.707-.707a1 1 0 00-1.414 1.414zm2.12-10.607a1 1 0 010 1.414l-.706.707a1 1 0 11-1.414-1.414l.707-.707a1 1 0 011.414 0zM17 11a1 1 0 100-2h-1a1 1 0 100 2h1zm-7 4a1 1 0 011 1v1a1 1 0 11-2 0v-1a1 1 0 011-1zM5.05 6.464A1 1 0 106.465 5.05l-.708-.707a1 1 0 00-1.414 1.414l.707.707zm1.414 8.486l-.707.707a1 1 0 01-1.414-1.414l.707-.707a1 1 0 011.414 1.414zM4 11a1 1 0 100-2H3a1 1 0 000 2h1z"
                        clipRule="evenodd"
                      ></path></svg
                    ><input
                      type="radio"
                      name="theme-toggle"
                      value="light"
                      title="Use light theme"
                      aria-label="Use light theme" /></label
                  ><label class
                    ><svg
                      xmlns="http://www.w3.org/2000/svg"
                      width="20"
                      height="20"
                      viewBox="0 0 20 20"
                      fill="currentColor"
                    >
                      <path
                        d="M17.293 13.293A8 8 0 016.707 2.707a8.001 8.001 0 1010.586 10.586z"
                      ></path></svg
                    ><input
                      type="radio"
                      name="theme-toggle"
                      value="dark"
                      title="Use dark theme"
                      aria-label="Use dark theme"
                  /></label></div
              ></astro-root>
            </div>
          </div>
        </nav>
      </aside>
    </main>
  </body>
</html>
{
"// Note": "this part could be in a import-map.json",
"imports": {
"astro/client/visible.js": "dist/assets/visible.hash.js",
"/src/components/ThemeToggleButton.tsx": "dist/assets/ThemeToggleButton.hash.js",
"@astrojs/renderer-preact/client.js": "dist/assets/preact-client.hash.js"
},
"routes": {
"/introduction": {
"entry": "dist/assets/introduction.hash.mjs",
"links": [
{ "rel": "stylesheet": "href": "../assets/introduction.hash.css" }
],
"modules": [
{ "src": "../href/assets/script.hash.js" }
]
}
}
}
@FredKSchott
Copy link

FredKSchott commented Dec 1, 2021

Looks great! A couple of quick thoughts:

  • I posted this comment last night in Jonathan's resolution RFC discussion and I think it's relevant here. Basically, I can't see a way that Astro.resolve() can continue to exist in a post-SSR world. I think @JonathanNeal might be tackling that in his RFC, and leaning more heavily on ESM imports for assets, which could be a great solution to the resolution problems that you're trying to solve here. We should all get together to chat.
  • If you're starting to get blocked by the lack of @component support, I'm happy to start pushing the core team to prioritize that discussion and even get high-level buy-in going into that RFC call. At least to the point where you could assume that something like it exists for you to use here.
  • I'm on board with adding the requirement that all directives are statically analyzable in the template. Basically, that <Component {...{'client:load': true}} /> is not supported and would result in a runtime error. The value of the directive could still be dynamic if needed, to support something like <Component client:visible={someVal} />.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment