0
Fork 0
mirror of https://github.com/withastro/astro.git synced 2024-12-16 21:46:22 -05:00

feat(next): ctx.isPrerendered (#11875)

This commit is contained in:
Florian Lefebvre 2024-09-05 16:58:23 +02:00 committed by GitHub
parent 70865b3cdc
commit a8a3d2cde8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
12 changed files with 97 additions and 16 deletions

View file

@ -0,0 +1,22 @@
---
'astro': minor
---
Adds a new property `isPrerendered` to the globals `Astro` and `APIContext` . This boolean value represents whether or not the current page is prerendered:
```astro
---
// src/pages/index.astro
export const prerender = true
---
```
```js
// src/middleware.js
export const onRequest = (ctx, next) => {
console.log(ctx.prerender) // it will log true
return next()
}
```

View file

@ -5,7 +5,7 @@
Adds a new property to the globals `Astro` and `APIContext` called `routePattern`. The `routePattern` represents the current route (component)
that is being rendered by Astro. It's usually a path pattern will look like this: `blog/[slug]`:
```asto
```astro
---
// src/pages/blog/[slug].astro
const route = Astro.routePattern;

View file

@ -21,7 +21,7 @@ export type Locals = {
};
export const onRequest = defineMiddleware(async (context, next) => {
if ((context as any)._isPrerendered) {
if (context.isPrerendered) {
if (context.request.method === 'POST') {
// eslint-disable-next-line no-console
console.warn(

View file

@ -70,6 +70,7 @@ function createContext({
},
});
},
isPrerendered: false,
get preferredLocale(): string | undefined {
return (preferredLocale ??= computePreferredLocale(request, userDefinedLocales));
},

View file

@ -107,8 +107,6 @@ export class RenderContext {
const { cookies, middleware, pipeline } = this;
const { logger, serverLike, streaming, manifest } = pipeline;
const isPrerendered = !serverLike || this.routeData.prerender;
const props =
Object.keys(this.props).length > 0
? this.props
@ -121,7 +119,7 @@ export class RenderContext {
serverLike,
base: manifest.base,
});
const apiContext = this.createAPIContext(props, isPrerendered);
const apiContext = this.createAPIContext(props);
this.counter++;
if (this.counter === 4) {
@ -208,7 +206,7 @@ export class RenderContext {
return response;
}
createAPIContext(props: APIContext['props'], isPrerendered: boolean): APIContext {
createAPIContext(props: APIContext['props']): APIContext {
const context = this.createActionAPIContext();
const redirect = (path: string, status = 302) =>
new Response(null, { status, headers: { Location: path } });
@ -218,11 +216,6 @@ export class RenderContext {
redirect,
getActionResult: createGetActionResult(context.locals),
callAction: createCallAction(context),
// Used internally by Actions middleware.
// TODO: discuss exposing this information from APIContext.
// middleware runs on prerendered routes in the dev server,
// so this is useful information to have.
_isPrerendered: isPrerendered,
});
}
@ -261,6 +254,7 @@ export class RenderContext {
return {
cookies,
routePattern: this.routeData.route,
isPrerendered: this.routeData.prerender,
get clientAddress() {
return renderContext.clientAddress();
},
@ -446,6 +440,7 @@ export class RenderContext {
generator: astroStaticPartial.generator,
glob: astroStaticPartial.glob,
routePattern: this.routeData.route,
isPrerendered: this.routeData.prerender,
cookies,
get clientAddress() {
return renderContext.clientAddress();

View file

@ -339,6 +339,11 @@ interface AstroSharedContext<
* The current locale computed from the URL of the request. It matches the locales in `i18n.locales`, and returns `undefined` otherwise.
*/
currentLocale: string | undefined;
/**
* Whether the current route is prerendered or not.
*/
isPrerendered: boolean;
}
/**

View file

@ -47,7 +47,7 @@ describe('Astro Global', () => {
);
});
it('Astro.route.pattern has the right value in pages and components', async () => {
it('Astro.routePattern has the right value in pages and components', async () => {
let html = await fixture.fetch('/blog').then((res) => res.text());
let $ = cheerio.load(html);
assert.match($('#pattern').text(), /Astro route pattern: \//);
@ -60,6 +60,18 @@ describe('Astro Global', () => {
/Astro route pattern middleware: \/omit-markdown-extensions/,
);
});
it('Astro.isPrerendered has the right value in pages and components', async () => {
let html = await fixture.fetch('/blog', {}).then((res) => res.text());
let $ = cheerio.load(html);
assert.match($('#prerender').text(), /Astro route prerender: true/);
assert.match($('#prerender-middleware').text(), /Astro route prerender middleware: true/);
html = await fixture.fetch('/blog/about', {}).then((res) => res.text());
$ = cheerio.load(html);
assert.match($('#prerender').text(), /Astro route prerender: false/);
assert.match($('#prerender-middleware').text(), /Astro route prerender middleware: false/);
});
});
describe('build', () => {
@ -96,7 +108,7 @@ describe('Astro Global', () => {
assert.equal($('.post-url[href]').length, 8);
});
it('Astro.route.pattern has the right value in pages and components', async () => {
it('Astro.routePattern has the right value in pages and components', async () => {
let html = await fixture.readFile('/index.html');
let $ = cheerio.load(html);
assert.match($('#pattern').text(), /Astro route pattern: \//);
@ -118,6 +130,19 @@ describe('Astro Global', () => {
'Astro route pattern middleware: /posts/[page]',
);
});
it('Astro.isPrerendered has the right value in pages and components', async () => {
let html = await fixture.readFile('/index.html');
let $ = cheerio.load(html);
assert.match($('#prerender').text(), /Astro route prerender: true/);
assert.match($('#prerender-middleware').text(), /Astro route prerender middleware: true/);
html = await fixture.readFile('/about/index.html');
$ = cheerio.load(html);
// It's prerendered since there's no adapter
assert.match($('#prerender').text(), /Astro route prerender: true/);
assert.match($('#prerender-middleware').text(), /Astro route prerender middleware: true/);
});
});
describe('app', () => {
@ -143,7 +168,7 @@ describe('Astro Global', () => {
assert.equal($('#site').attr('href'), 'https://mysite.dev/subsite/');
});
it('Astro.route.pattern has the right value in pages and components', async () => {
it('Astro.routePattern has the right value in pages and components', async () => {
let response = await app.render(new Request('https://example.com/'));
let html = await response.text();
let $ = cheerio.load(html);
@ -158,6 +183,19 @@ describe('Astro Global', () => {
/Astro route pattern middleware: \/omit-markdown-extensions/,
);
});
it('Astro.isPrerendered has the right value in pages and components', async () => {
let html = await app.render(new Request('https://example.com/')).then((res) => res.text());
let $ = cheerio.load(html);
// It's NOT prerendered since there's an adapter + output server
assert.match($('#prerender').text(), /Astro route prerender: false/);
assert.match($('#prerender-middleware').text(), /Astro route prerender middleware: false/);
html = await app.render(new Request('https://example.com/about')).then((res) => res.text());
$ = cheerio.load(html);
assert.match($('#prerender').text(), /Astro route prerender: false/);
assert.match($('#prerender-middleware').text(), /Astro route prerender middleware: false/);
});
});
});

View file

@ -1,6 +1,10 @@
---
const pattern = Astro.routePattern;
const localsPattern = Astro.locals.localsPattern;
const isPrerendered = JSON.stringify(Astro.isPrerendered);
const localsPrerendered = JSON.stringify(Astro.locals.localsPrerendered);
---
<p id="pattern">Astro route pattern: {pattern}</p>
<p id="pattern-middleware">Astro route pattern middleware: {localsPattern}</p>
<p id="prerender">Astro route prerender: {isPrerendered}</p>
<p id="prerender-middleware">Astro route prerender middleware: {localsPrerendered}</p>

View file

@ -2,7 +2,8 @@
export function onRequest(ctx, next) {
ctx.locals = {
localsPattern: ctx.routePattern
localsPattern: ctx.routePattern,
localsPrerendered: ctx.isPrerendered
};
return next()
}

View file

@ -0,0 +1,13 @@
---
import Route from '../components/Route.astro'
export const prerender = false
---
<html>
<head>
<title>Test</title>
</head>
<body>
<Route />
</body>
</html>

View file

@ -9,7 +9,7 @@ const data = await Astro.glob('./post/**/*');
<body>
{data.map((page: any) => (
<div>
<h1 data-file={page.file} />Title</h1>
<h1 data-file={page.file}>Title</h1>
<a class="post-url" href={page.url}>Read</a>
</div>
))}

View file

@ -8752,10 +8752,12 @@ packages:
libsql@0.3.19:
resolution: {integrity: sha512-Aj5cQ5uk/6fHdmeW0TiXK42FqUlwx7ytmMLPSaUQPin5HKKKuUPD62MAbN4OEweGBBI7q1BekoEN4gPUEL6MZA==}
cpu: [x64, arm64, wasm32]
os: [darwin, linux, win32]
libsql@0.4.1:
resolution: {integrity: sha512-qZlR9Yu1zMBeLChzkE/cKfoKV3Esp9cn9Vx5Zirn4AVhDWPcjYhKwbtJcMuHehgk3mH+fJr9qW+3vesBWbQpBg==}
cpu: [x64, arm64, wasm32]
os: [darwin, linux, win32]
lilconfig@2.1.0: