final pass at Outlet approach

This commit is contained in:
Nate Moore 2023-05-16 09:46:49 -05:00
parent d8608bb947
commit 976b6ccf6e
10 changed files with 74 additions and 43 deletions

View file

@ -0,0 +1 @@
Hello world!

View file

@ -1 +1,2 @@
/// <reference path="../.astro/types.d.ts" />
/// <reference types="astro/client" />

View file

@ -15,16 +15,31 @@ import { Outlet } from 'astro/components';
<h1>My Website</h1>
</header>
<slot name="nav" />
<Outlet id="nav">
<slot name="nav" />
</Outlet>
<main>
{() => new Promise((resolve) => setTimeout(resolve, 1000))}
<slot />
<Outlet id="main">
<slot />
</Outlet>
{() => new Promise((resolve) => setTimeout(resolve, 1000))}
<slot name="tabs" />
</main>
<style is:global>
nav ul {
list-style: none;
margin: 0;
padding: 0;
display: flex;
gap: 1rem;
}
a.active {
color: red;
}
</style>
<script>
function getOutlets() {
const query = "//comment()[contains(., 'astro:outlet')]";
@ -98,6 +113,7 @@ import { Outlet } from 'astro/components';
async function update() {
const promises: any[] = [];
for (const [outlet, range] of Object.entries(getOutlets())) {
console.log({ outlet });
promises.push(
fetch(event.destination.url, {
headers: { 'x-astro-outlet': outlet },
@ -115,18 +131,5 @@ import { Outlet } from 'astro/components';
});
});
</script>
<style is:global>
nav ul {
list-style: none;
margin: 0;
padding: 0;
display: flex;
gap: 1rem;
}
a.active {
color: red;
}
</style>
</body>
</html>

View file

@ -1,11 +1,18 @@
---
import Layout from '../layouts/Default.astro';
import { getEntryBySlug } from 'astro:content';
const entry = await getEntryBySlug('posts', 'intro');
const { Content } = await entry.render();
---
<Layout>
<div>
<h2>Home</h2>
<p>Streaming partials!</p>
<Content />
</div>
<nav slot="nav">

View file

@ -31,6 +31,11 @@ const { title, description } = Astro.props;
addEventListener('load', () => document.documentElement.classList.add('loaded'));
</script>
<script>
import listen from 'micromorph/spa';
listen();
</script>
<style>
:root {
--_placeholder-bg: linear-gradient(transparent, transparent);

View file

@ -6,7 +6,7 @@ interface Props {
const { id } = Astro.props;
// @ts-ignore untyped internals
// $$result.outlets.set(id, $$slots.default);
$$result.outlets.set(id, () => Astro.slots.render('default'));
---
<Fragment set:html={`<!--astro:outlet ${id}-->`} /><slot /><Fragment

View file

@ -113,11 +113,11 @@
"test:e2e:match": "playwright test -g"
},
"dependencies": {
"@astrojs/compiler": "^1.4.0",
"@astrojs/language-server": "^1.0.0",
"@astrojs/markdown-remark": "^2.2.0",
"@astrojs/telemetry": "^2.1.1",
"@astrojs/webapi": "^2.1.1",
"@astrojs/compiler": "^1.4.1",
"@astrojs/language-server": "^0.28.3",
"@astrojs/markdown-remark": "^2.1.4",
"@astrojs/telemetry": "^2.1.0",
"@astrojs/webapi": "^2.1.0",
"@babel/core": "^7.18.2",
"@babel/generator": "^7.18.2",
"@babel/parser": "^7.18.4",

View file

@ -83,7 +83,7 @@ export function createAstroComponentInstance(
const instance = new AstroComponentInstance(result, props, slots, factory);
if (result._metadata.request.headers.has('x-astro-outlet')) {
for (const [name, slot] of Object.entries(slots)) {
result.outletPropagators.set(`${factory.hash} ${name}`, slot);
result.outletPropagators.set(name, slot);
}
return instance;
}

View file

@ -70,14 +70,13 @@ async function bufferHeadContent(result: SSRResult) {
// Recursively calls component instances that might have slots to be propagated up.
async function bufferSlottedContent(result: SSRResult, outlet: string) {
const iterator = result.outletPropagators.entries();
let promises = [];
while (true) {
const { value: [name, slot] = [], done } = iterator.next();
if (done) {
break;
}
const returnValue = await slot(result);
result.outlets.set(name, returnValue);
// TODO: exhaust all expressions
if (name === outlet) {
break;
}
@ -153,6 +152,8 @@ export async function renderPage(
result.scripts.clear();
await bufferSlottedContent(result, outlet);
console.log(result.outlets);
if (!result.outlets.get(outlet)) {
let init = result.response;
let headers = new Headers(init.headers);

View file

@ -535,19 +535,19 @@ importers:
packages/astro:
dependencies:
'@astrojs/compiler':
specifier: ^1.4.0
version: 1.4.0
specifier: ^1.4.1
version: 1.4.1
'@astrojs/language-server':
specifier: ^1.0.0
version: 1.0.0
specifier: ^0.28.3
version: 0.28.3
'@astrojs/markdown-remark':
specifier: ^2.2.0
specifier: ^2.1.4
version: link:../markdown/remark
'@astrojs/telemetry':
specifier: ^2.1.1
specifier: ^2.1.0
version: link:../telemetry
'@astrojs/webapi':
specifier: ^2.1.1
specifier: ^2.1.0
version: link:../webapi
'@babel/core':
specifier: ^7.18.2
@ -5393,20 +5393,22 @@ packages:
sisteransi: 1.0.5
dev: false
/@astrojs/compiler@1.4.0:
resolution: {integrity: sha512-Vav3a32Ct+omowV9X9kDM2ghWAvFdjZkv5BdvBjZCKYbFVT6//IZApDIVbHI1UPuLuD2sKyLWx2T+E7clqUJdg==}
/@astrojs/compiler@0.31.4:
resolution: {integrity: sha512-6bBFeDTtPOn4jZaiD3p0f05MEGQL9pw2Zbfj546oFETNmjJFWO3nzHz6/m+P53calknCvyVzZ5YhoBLIvzn5iw==}
dev: false
/@astrojs/language-server@1.0.0:
resolution: {integrity: sha512-oEw7AwJmzjgy6HC9f5IdrphZ1GVgfV/+7xQuyf52cpTiRWd/tJISK3MsKP0cDkVlfodmNABNFnAaAWuLZEiiiA==}
/@astrojs/compiler@1.4.1:
resolution: {integrity: sha512-aXAxapNWZwGN41P+Am/ma/2kAzKOhMNaY6YuvLkUHFv+UZkmDHD6F0fE1sQA2Up0bLjgPQa1VQzoAaii5tZWaA==}
/@astrojs/language-server@0.28.3:
resolution: {integrity: sha512-fPovAX/X46eE2w03jNRMpQ7W9m2mAvNt4Ay65lD9wl1Z5vIQYxlg7Enp9qP225muTr4jSVB5QiLumFJmZMAaVA==}
hasBin: true
dependencies:
'@astrojs/compiler': 1.4.0
'@jridgewell/trace-mapping': 0.3.18
'@vscode/emmet-helper': 2.8.8
events: 3.3.0
prettier: 2.8.8
prettier-plugin-astro: 0.8.0
synckit: 0.8.5
prettier-plugin-astro: 0.7.2
source-map: 0.7.4
vscode-css-languageservice: 6.2.5
vscode-html-languageservice: 5.0.5
vscode-languageserver: 8.1.0
@ -8436,7 +8438,7 @@ packages:
/@ts-morph/common@0.16.0:
resolution: {integrity: sha512-SgJpzkTgZKLKqQniCjLaE3c2L2sdL7UShvmTmPBejAKd2OKV/yfMpQ2IWpAuA+VY5wy7PkSUaEObIqEK6afFuw==}
dependencies:
fast-glob: 3.2.11
fast-glob: 3.2.12
minimatch: 5.1.6
mkdirp: 1.0.4
path-browserify: 1.0.1
@ -15247,14 +15249,25 @@ packages:
fast-diff: 1.2.0
dev: true
/prettier-plugin-astro@0.7.2:
resolution: {integrity: sha512-mmifnkG160BtC727gqoimoxnZT/dwr8ASxpoGGl6EHevhfblSOeu+pwH1LAm5Qu1MynizktztFujHHaijLCkww==}
engines: {node: ^14.15.0 || >=16.0.0, pnpm: '>=7.14.0'}
dependencies:
'@astrojs/compiler': 0.31.4
prettier: 2.8.8
sass-formatter: 0.7.6
synckit: 0.8.5
dev: false
/prettier-plugin-astro@0.8.0:
resolution: {integrity: sha512-kt9wk33J7HvFGwFaHb8piwy4zbUmabC8Nu+qCw493jhe96YkpjscqGBPy4nJ9TPy9pd7+kEx1zM81rp+MIdrXg==}
engines: {node: ^14.15.0 || >=16.0.0, pnpm: '>=7.14.0'}
dependencies:
'@astrojs/compiler': 1.4.0
'@astrojs/compiler': 1.4.1
prettier: 2.8.8
sass-formatter: 0.7.6
synckit: 0.8.5
dev: true
/prettier@2.8.8:
resolution: {integrity: sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==}