[ci] yarn format
This commit is contained in:
parent
166e22bdf3
commit
f51f6c85d1
21 changed files with 86 additions and 66 deletions
|
@ -3,6 +3,7 @@ layout: ~/layouts/Main.astro
|
|||
title: Island Architecture
|
||||
draft: true
|
||||
---
|
||||
|
||||
<!--
|
||||
@aFuzzyBear: I have been spending most the day learning more about Island Architecture, wrote plenty of notes, listened to Fred K Schott's interview on Speakeasy(https://www.youtube.com/watch?v=mgkwZqVkrwo) and the interview with Jason Lengstrof (https://www.youtube.com/watch?v=z15YLsLMtu4)
|
||||
Figured I might give writing this a wee go,
|
||||
|
@ -29,7 +30,7 @@ In the summer of 2020, he managed to formulated his thoughts of how web architec
|
|||
|
||||
His seminal post outlines and discusses the general concept of 'islands' as an architectural design process that could be used in Web Development, allowing for better improvements in overall site performance, SEO, UX, and everywhere else. His given explanation describing this new paradigm, was extraordinarily succinct:
|
||||
|
||||
> "The general idea of an *“Islands”* architecture is deceptively simple: Render HTML pages on the server, and inject placeholders or slots around highly dynamic regions. These placeholders/slots contain the server-rendered HTML output from their corresponding widget. They denote regions that can then be "hydrated" on the client into small self-contained widgets, reusing their server-rendered initial HTML."-Jason Miller
|
||||
> "The general idea of an _“Islands”_ architecture is deceptively simple: Render HTML pages on the server, and inject placeholders or slots around highly dynamic regions. These placeholders/slots contain the server-rendered HTML output from their corresponding widget. They denote regions that can then be "hydrated" on the client into small self-contained widgets, reusing their server-rendered initial HTML."-Jason Miller
|
||||
|
||||
To develop a better understanding of what Jason meant with his proposal, let's quickly explore the backdrop, before we explain 'Island Architecture' and how it is applied into Astro as our primary ethos.
|
||||
|
||||
|
@ -37,7 +38,7 @@ To develop a better understanding of what Jason meant with his proposal, let's q
|
|||
|
||||
Think of a simple webpage. On which are many different types of components that are shown on this page, components that are shared across the site, others contain fixed content, some are a bit more elaborate that may perhaps use different state's or need to fetch multiple data streams from external sources.
|
||||
|
||||
Such an site would would have very few actual 'moving' pieces, or *dynamic* elements. For the most part the content tends to be fixed, and static.
|
||||
Such an site would would have very few actual 'moving' pieces, or _dynamic_ elements. For the most part the content tends to be fixed, and static.
|
||||
|
||||
In order to allow for dynamism and interactivity we are often left making overly complex solutions to deliver the slightest form of action on the application.
|
||||
|
||||
|
@ -47,13 +48,13 @@ Given the [catalogue of patterns](https://en.wikipedia.org/wiki/List_of_software
|
|||
|
||||
Web developers tend to gravitate towards tried and tested practices, and none fit the requirements better than the [Model-View-Controller](https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller) (**MVC**) design pattern.
|
||||
|
||||
Where the **Model** contains the data structures and logic that governs the use of the data in the application. **Views** are the visual representation of the data that the user sees, and the **Controller** connects the views to their relevant data *Models* based on their interactions with the User.
|
||||
Where the **Model** contains the data structures and logic that governs the use of the data in the application. **Views** are the visual representation of the data that the user sees, and the **Controller** connects the views to their relevant data _Models_ based on their interactions with the User.
|
||||
|
||||
This design pattern works well for our [client-server](https://en.wikipedia.org/wiki/Client%E2%80%93server_model) based applications. Since the models are placed on the *servers*, the views that are sent back over the wire tend to be static *documents*, controllers are sent along with the static files to facilitate the behaviours that web developers created for their application, in the form of *scripts*.
|
||||
This design pattern works well for our [client-server](https://en.wikipedia.org/wiki/Client%E2%80%93server_model) based applications. Since the models are placed on the _servers_, the views that are sent back over the wire tend to be static _documents_, controllers are sent along with the static files to facilitate the behaviours that web developers created for their application, in the form of _scripts_.
|
||||
|
||||
## Rise of the Frameworks
|
||||
|
||||
A vast swathe of libraries, frameworks and tooling rose up to meet the challenges of providing a Developer Experience (DX) that would let them create their applications, *'freely'*.
|
||||
A vast swathe of libraries, frameworks and tooling rose up to meet the challenges of providing a Developer Experience (DX) that would let them create their applications, _'freely'_.
|
||||
|
||||
Helping to abstract away much of the complexity needed in implementing architectural design decisions into their application.
|
||||
|
||||
|
@ -137,7 +138,7 @@ Into this new age ESM world, we have had a dearth of innovation from the establi
|
|||
|
||||
Basic questions of : Websites or WebApp's were still unresolved. Where to render the site, on the server or on the client, perhaps a bit of both? What determines the need for dynamic content and what specifies content to be static?
|
||||
|
||||
Witnessing frameworks slowly go full circle and return to Server-Side-Rendering (*SSR*) their applications was in part only allowed to be considered in an ESM world, however it was bit of an admission of culpability of sorts.
|
||||
Witnessing frameworks slowly go full circle and return to Server-Side-Rendering (_SSR_) their applications was in part only allowed to be considered in an ESM world, however it was bit of an admission of culpability of sorts.
|
||||
|
||||
By inadvertently admitting that the current model is flawed, opened up the space for a new form of discourse to enter, and help redefine the ecosystem moving forward.
|
||||
|
||||
|
@ -155,15 +156,15 @@ In the introduction we placed a quote from Jason, describing the general concept
|
|||
|
||||
Jason asks us to think of a Island architecture as a static HTML document. One that is rendered entirely on the server.
|
||||
|
||||
The document contains multiple separate embedded applications, that are injected into placeholders or '*slots*', which form dynamic regions on the page.
|
||||
The document contains multiple separate embedded applications, that are injected into placeholders or '_slots_', which form dynamic regions on the page.
|
||||
|
||||
The Server renders HTML outputs form each of these dynamic components, and places them onto the static document being sent back down to the End-User.
|
||||
|
||||
These slots, of dynamic regions, can then be '*hydrated*'. [Hydration](https://en.wikipedia.org/wiki/Hydration_(web_development)) is a process that allows for Client-Sided JS to convert and make static HTML, dynamic, reusing their initial server-rendered HTML.
|
||||
These slots, of dynamic regions, can then be '_hydrated_'. [Hydration](<https://en.wikipedia.org/wiki/Hydration_(web_development)>) is a process that allows for Client-Sided JS to convert and make static HTML, dynamic, reusing their initial server-rendered HTML.
|
||||
|
||||
This 'micro' architecture is similar to both 'micro-frontends' and 'micro-services'. Both share the concept of breaking applications into small indivisible units. But the problem is that a lot of the small modular units are rarely composed in HTML.
|
||||
|
||||
With Island-Architecture, he proposes a form of progressive enhancement for the dynamic components by using a technique known as *Partial Hydration*.
|
||||
With Island-Architecture, he proposes a form of progressive enhancement for the dynamic components by using a technique known as _Partial Hydration_.
|
||||
|
||||
Lets look at this following analogy:
|
||||
|
||||
|
@ -181,7 +182,7 @@ This would then load the functionality for the carousel in-place, transforming i
|
|||
|
||||
## Island Hydration
|
||||
|
||||
By now the idea of Island-architecture must be settling in, and one must be thinking, this is just [Progressive Hydration](https://en.wikipedia.org/wiki/Hydration_(web_development)#Progressive_rehydration), and you wouldn't be overly off mark.
|
||||
By now the idea of Island-architecture must be settling in, and one must be thinking, this is just [Progressive Hydration](<https://en.wikipedia.org/wiki/Hydration_(web_development)#Progressive_rehydration>), and you wouldn't be overly off mark.
|
||||
|
||||
Progressive Hydration that is used in frameworks like: Angluar, React, Preact, Vue. Are individual components, which are loaded and then initialised over a period of time.
|
||||
|
||||
|
@ -197,7 +198,7 @@ Since there is no outer `<div id='root'>` element that needs to be initialised b
|
|||
|
||||
Every region of the page is an isolated unit, an island, on its own, connected to others by the HTML page. With such an approach the benefits do begin to stack up.
|
||||
|
||||
A key benefit is seen with the site performance. Since isolation is inherent, if a single issue affects a component, it wouldn't affect the other *islands* on the page.
|
||||
A key benefit is seen with the site performance. Since isolation is inherent, if a single issue affects a component, it wouldn't affect the other _islands_ on the page.
|
||||
|
||||
## Exploring the Island
|
||||
|
||||
|
@ -205,7 +206,7 @@ As we explore further into the Island, we can see immediate trade differences be
|
|||
|
||||
Quickly wandering back to the Status Quo for a brief interlude. We use SSR with SPA's to help tackle the downside of SPA's and its SEO. Appealing to the search engines in this manner has another negative affect on the UX.
|
||||
|
||||
>"...visitors are left waiting for the actual functionality of a page to arrive while staring at a frustratingly fake version of that page." - Jason Miller
|
||||
> "...visitors are left waiting for the actual functionality of a page to arrive while staring at a frustratingly fake version of that page." - Jason Miller
|
||||
|
||||
There are other issues that stem from traditional SSR, and being idly unawares of such performance pitfalls, gives rise to an orchestra of potential problems.
|
||||
|
||||
|
|
|
@ -53,7 +53,7 @@ For best results, you should only have one `<style>` tag per-Astro component. Th
|
|||
<html>
|
||||
<head>
|
||||
<style>
|
||||
...
|
||||
...;
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
|
|
@ -208,4 +208,3 @@ export async function createCollection() {
|
|||
- API Reference: [collection](/reference/api-reference#collections-api)
|
||||
- API Reference: [createCollection()](/reference/api-reference#createcollection)
|
||||
- API Reference: [Creating an RSS feed](/reference/api-reference#rss-feed)
|
||||
|
||||
|
|
|
@ -51,8 +51,6 @@ Besides the obvious performance benefits of sending less JavaScript down to the
|
|||
|
||||
![diagram](https://res.cloudinary.com/wedding-website/image/upload/v1596766231/islands-architecture-1.png)
|
||||
|
||||
|
||||
|
||||
## Hydrate Interactive Components
|
||||
|
||||
Astro renders every component on the server **at build time**. To hydrate components on the client **at runtime**, you may use any of the following `client:*` directives. A directive is a component attribute (always with a `:`) which tells Astro how your component should be rendered.
|
||||
|
@ -68,15 +66,19 @@ import MyReactComponent from '../components/MyReactComponent.jsx';
|
|||
```
|
||||
|
||||
### `<MyComponent client:load />`
|
||||
|
||||
Hydrate the component on page load.
|
||||
|
||||
### `<MyComponent client:idle />`
|
||||
|
||||
Hydrate the component as soon as main thread is free (uses [requestIdleCallback()][mdn-ric]).
|
||||
|
||||
### `<MyComponent client:visible />`
|
||||
|
||||
Hydrate the component as soon as the element enters the viewport (uses [IntersectionObserver][mdn-io]). Useful for content lower down on the page.
|
||||
|
||||
### `<MyComponent client:media={QUERY} />`
|
||||
|
||||
Hydrate the component as soon as the browser matches the given media query (uses [matchMedia][mdn-mm]). Useful for sidebar toggles, or other elements that should only display on mobile or desktop devices.
|
||||
|
||||
## Can I Hydrate Astro Components?
|
||||
|
|
|
@ -54,12 +54,10 @@ import BaseLayout from '../layouts/BaseLayout.astro'
|
|||
</BaseLayout>
|
||||
```
|
||||
|
||||
|
||||
## Nesting Layouts
|
||||
|
||||
You can nest layouts when you want to create more specific page types without copy-pasting. It is common in Astro to have one generic `BaseLayout` and then many more specific layouts (`PostLayout`, `ProductLayout`, etc.) that reuse and build on top of it.
|
||||
|
||||
|
||||
```astro
|
||||
---
|
||||
// src/layouts/PostLayout.astro
|
||||
|
@ -126,6 +124,7 @@ Layouts are essential for Markdown files. Markdown files can declare a layout in
|
|||
title: Blog Post
|
||||
layout: ../layouts/PostLayout.astro
|
||||
---
|
||||
|
||||
This blog post will be **rendered** inside of the `<PostLayout />` layout.
|
||||
```
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@ Astro includes an opinionated folder layout for your project. Every Astro projec
|
|||
- `package.json` - A project manifest.
|
||||
|
||||
The easiest way to set up your new project is with `npm init astro`. Check out our [Installation Guide](/quick-start) for a walkthrough of how to set up your project automatically (with `npm init astro`) or manually.
|
||||
|
||||
## Project Structure
|
||||
|
||||
```
|
||||
|
|
|
@ -20,8 +20,6 @@ The following guides are based on some shared assumptions:
|
|||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
## Building The App
|
||||
|
||||
You may run `npm run build` command to build the app.
|
||||
|
@ -65,7 +63,8 @@ By default, the build output will be placed at `dist/`. You may deploy this `dis
|
|||
|
||||
cd -
|
||||
```
|
||||
> You can also run the above script in your CI setup to enable automatic deployment on each push.
|
||||
|
||||
> You can also run the above script in your CI setup to enable automatic deployment on each push.
|
||||
|
||||
### GitHub Actions
|
||||
|
||||
|
@ -138,8 +137,8 @@ Then, set up a new project on [Netlify](https://netlify.com) from your chosen Gi
|
|||
|
||||
If you don't want to use the `netlify.toml`, when you go to [Netlify](https://netlify.com) and set up up a new project from Git, input the following settings:
|
||||
|
||||
- **Build Command:** `astro build` or `npm run build`
|
||||
- **Publish directory:** `dist`
|
||||
- **Build Command:** `astro build` or `npm run build`
|
||||
- **Publish directory:** `dist`
|
||||
|
||||
Then hit the deploy button.
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@ export function getUser() {
|
|||
}
|
||||
|
||||
// src/index.js
|
||||
import {getUser} from './user.js';
|
||||
import { getUser } from './user.js';
|
||||
```
|
||||
|
||||
All browsers now support ESM, so Astro is able to ship this code directly to the browser during development.
|
||||
|
|
|
@ -43,7 +43,10 @@ You can provide names of the plugins as well as import them:
|
|||
// astro.config.js
|
||||
export default {
|
||||
markdownOptions: {
|
||||
remarkPlugins: [import('remark-slug'), [import('remark-autolink-headings'), { behavior: 'prepend' }]],
|
||||
remarkPlugins: [
|
||||
import('remark-slug'),
|
||||
[import('remark-autolink-headings'), { behavior: 'prepend' }],
|
||||
],
|
||||
},
|
||||
};
|
||||
```
|
||||
|
|
|
@ -65,6 +65,7 @@ const data = Astro.fetchContent('../pages/post/*.md'); // returns an array of po
|
|||
`Astro.site` returns a `URL` made from `buildOptions.site` in your Astro config. If undefined, this will return a URL generated from `localhost`.
|
||||
|
||||
## Collections API
|
||||
|
||||
### `collection` prop
|
||||
|
||||
```jsx
|
||||
|
@ -158,7 +159,12 @@ Astro will generate an RSS 2.0 feed at `/feed/[collection].xml` (for example, `/
|
|||
⚠️ Even though Astro will create the RSS feed for you, you’ll still need to add `<link>` tags manually in your `<head>` HTML:
|
||||
|
||||
```html
|
||||
<link rel="alternate" type="application/rss+xml" title="My RSS Feed" href="/feed/podcast.xml" />
|
||||
<link
|
||||
rel="alternate"
|
||||
type="application/rss+xml"
|
||||
title="My RSS Feed"
|
||||
href="/feed/podcast.xml"
|
||||
/>
|
||||
```
|
||||
|
||||
## `import.meta`
|
||||
|
@ -176,4 +182,3 @@ export default function () {
|
|||
```
|
||||
|
||||
[canonical]: https://en.wikipedia.org/wiki/Canonical_link_element
|
||||
|
||||
|
|
|
@ -17,8 +17,8 @@ import { Markdown } from 'astro/components';
|
|||
```
|
||||
|
||||
See our [Markdown Guide](/guides/markdown-content) for more info.
|
||||
<!-- TODO: We should move some of the specific component info here. -->
|
||||
|
||||
<!-- TODO: We should move some of the specific component info here. -->
|
||||
|
||||
## `<Prism />`
|
||||
|
||||
|
|
|
@ -21,7 +21,12 @@ export default {
|
|||
// tailwindConfig: '', // Path to tailwind.config.js if used, e.g. './tailwind.config.js'
|
||||
},
|
||||
// component renderers which are enabled by default
|
||||
renderers: ['@astrojs/renderer-svelte', '@astrojs/renderer-vue', '@astrojs/renderer-react', '@astrojs/renderer-preact'],
|
||||
renderers: [
|
||||
'@astrojs/renderer-svelte',
|
||||
'@astrojs/renderer-vue',
|
||||
'@astrojs/renderer-react',
|
||||
'@astrojs/renderer-preact',
|
||||
],
|
||||
};
|
||||
```
|
||||
|
||||
|
|
|
@ -120,10 +120,13 @@ Note that `childHTML` is an HTML string representing this component's children.
|
|||
```js
|
||||
import { h, renderToString } from 'xxx';
|
||||
|
||||
const Wrapper = ({ value }) => h('astro-fragment', { dangerouslySetInnerHTML: { __html: value } });
|
||||
const Wrapper = ({ value }) =>
|
||||
h('astro-fragment', { dangerouslySetInnerHTML: { __html: value } });
|
||||
|
||||
function renderToStaticMarkup(Component, props, childHTML) {
|
||||
const html = renderToString(h(Component, props, h(Wrapper, { value: childHTML })));
|
||||
const html = renderToString(
|
||||
h(Component, props, h(Wrapper, { value: childHTML }))
|
||||
);
|
||||
return { html };
|
||||
}
|
||||
```
|
||||
|
@ -152,7 +155,10 @@ import SharedWrapper from './SharedWrapper.js';
|
|||
|
||||
export default (element) => {
|
||||
return (Component, props, childHTML) => {
|
||||
hydrate(h(Component, props, h(SharedWrapper, { value: childHTML })), element);
|
||||
hydrate(
|
||||
h(Component, props, h(SharedWrapper, { value: childHTML })),
|
||||
element
|
||||
);
|
||||
};
|
||||
};
|
||||
```
|
||||
|
|
Loading…
Reference in a new issue