mirror of
https://github.com/withastro/astro.git
synced 2024-12-30 22:03:56 -05:00
optimization(runtime): create smaller objects for each Astro global (#10773)
* optimization(runtime): create smaller objects for each Astro global * add changeset * Make slots lazy --------- Co-authored-by: bluwy <bjornlu.dev@gmail.com>
This commit is contained in:
parent
5750ad12be
commit
35e43ecdaa
2 changed files with 54 additions and 10 deletions
5
.changeset/lazy-rats-beam.md
Normal file
5
.changeset/lazy-rats-beam.md
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
"astro": patch
|
||||
---
|
||||
|
||||
Improves performance for frequent use of small components.
|
|
@ -242,12 +242,57 @@ export class RenderContext {
|
|||
return result;
|
||||
}
|
||||
|
||||
#astroPagePartial?: Omit<AstroGlobal, 'props' | 'self' | 'slots'>;
|
||||
/**
|
||||
* The Astro global is sourced in 3 different phases:
|
||||
* - **Static**: `.generator` and `.glob` is printed by the compiler, instantiated once per process per astro file
|
||||
* - **Page-level**: `.request`, `.cookies`, `.locals` etc. These remain the same for the duration of the request.
|
||||
* - **Component-level**: `.props`, `.slots`, and `.self` are unique to each _use_ of each component.
|
||||
*
|
||||
* The page level partial is used as the prototype of the user-visible `Astro` global object, which is instantiated once per use of a component.
|
||||
*/
|
||||
createAstro(
|
||||
result: SSRResult,
|
||||
astroGlobalPartial: AstroGlobalPartial,
|
||||
astroStaticPartial: AstroGlobalPartial,
|
||||
props: Record<string, any>,
|
||||
slotValues: Record<string, any> | null
|
||||
): AstroGlobal {
|
||||
// Create page partial with static partial so they can be cached together.
|
||||
const astroPagePartial = (this.#astroPagePartial ??= this.createAstroPagePartial(
|
||||
result,
|
||||
astroStaticPartial
|
||||
));
|
||||
// Create component-level partials. `Astro.self` is added by the compiler.
|
||||
const astroComponentPartial = { props, self: null };
|
||||
|
||||
// Create final object. `Astro.slots` will be lazily created.
|
||||
const Astro: Omit<AstroGlobal, 'self' | 'slots'> = Object.assign(
|
||||
Object.create(astroPagePartial),
|
||||
astroComponentPartial
|
||||
);
|
||||
|
||||
// Handle `Astro.slots`
|
||||
let _slots: AstroGlobal['slots'];
|
||||
Object.defineProperty(Astro, 'slots', {
|
||||
get: () => {
|
||||
if (!_slots) {
|
||||
_slots = new Slots(
|
||||
result,
|
||||
slotValues,
|
||||
this.pipeline.logger
|
||||
) as unknown as AstroGlobal['slots'];
|
||||
}
|
||||
return _slots;
|
||||
},
|
||||
});
|
||||
|
||||
return Astro as AstroGlobal;
|
||||
}
|
||||
|
||||
createAstroPagePartial(
|
||||
result: SSRResult,
|
||||
astroStaticPartial: AstroGlobalPartial
|
||||
): Omit<AstroGlobal, 'props' | 'self' | 'slots'> {
|
||||
const renderContext = this;
|
||||
const { cookies, locals, params, pipeline, request, url } = this;
|
||||
const { response } = result;
|
||||
|
@ -260,12 +305,10 @@ export class RenderContext {
|
|||
}
|
||||
return new Response(null, { status, headers: { Location: path } });
|
||||
};
|
||||
const slots = new Slots(result, slotValues, pipeline.logger) as unknown as AstroGlobal['slots'];
|
||||
|
||||
// `Astro.self` is added by the compiler
|
||||
const astroGlobalCombined: Omit<AstroGlobal, 'self'> = {
|
||||
generator: astroGlobalPartial.generator,
|
||||
glob: astroGlobalPartial.glob,
|
||||
return {
|
||||
generator: astroStaticPartial.generator,
|
||||
glob: astroStaticPartial.glob,
|
||||
cookies,
|
||||
get clientAddress() {
|
||||
return renderContext.clientAddress();
|
||||
|
@ -280,17 +323,13 @@ export class RenderContext {
|
|||
get preferredLocaleList() {
|
||||
return renderContext.computePreferredLocaleList();
|
||||
},
|
||||
props,
|
||||
locals,
|
||||
redirect,
|
||||
request,
|
||||
response,
|
||||
slots,
|
||||
site: pipeline.site,
|
||||
url,
|
||||
};
|
||||
|
||||
return astroGlobalCombined as AstroGlobal;
|
||||
}
|
||||
|
||||
clientAddress() {
|
||||
|
|
Loading…
Reference in a new issue