mirror of
https://github.com/withastro/astro.git
synced 2025-03-24 23:21:57 -05:00
community onboarding: codebase documentation around runtime (#10612)
* document runtime * apply suggestions from code review
This commit is contained in:
parent
a544f4cc0e
commit
e9afd67139
8 changed files with 150 additions and 39 deletions
|
@ -2352,7 +2352,9 @@ interface AstroSharedContext<
|
|||
RouteParams extends Record<string, string | undefined> = Record<string, string | undefined>,
|
||||
> {
|
||||
/**
|
||||
* The address (usually IP address) of the user. Used with SSR only.
|
||||
* The address (usually IP address) of the user.
|
||||
*
|
||||
* Throws an error if used within a static site, or within a prerendered page.
|
||||
*/
|
||||
clientAddress: string;
|
||||
/**
|
||||
|
@ -2402,15 +2404,33 @@ interface AstroSharedContext<
|
|||
currentLocale: string | undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* The `APIContext` is the object made available to endpoints and middleware.
|
||||
* It is a subset of the `Astro` global object available in pages.
|
||||
*
|
||||
* [Reference](https://docs.astro.build/en/reference/api-reference/#endpoint-context)
|
||||
*/
|
||||
export interface APIContext<
|
||||
Props extends Record<string, any> = Record<string, any>,
|
||||
APIParams extends Record<string, string | undefined> = Record<string, string | undefined>,
|
||||
> extends AstroSharedContext<Props, Params> {
|
||||
/**
|
||||
* The site provided in the astro config, parsed as an instance of `URL`, without base.
|
||||
* `undefined` if the site is not provided in the config.
|
||||
*/
|
||||
site: URL | undefined;
|
||||
/**
|
||||
* A human-readable string representing the Astro version used to create the project.
|
||||
* For example, `"Astro v1.1.1"`.
|
||||
*/
|
||||
generator: string;
|
||||
/**
|
||||
* A full URL object of the request URL.
|
||||
* Equivalent to: `new URL(request.url)`
|
||||
* The url of the current request, parsed as an instance of `URL`.
|
||||
*
|
||||
* Equivalent to:
|
||||
* ```ts
|
||||
* new URL(context.request.url)
|
||||
* ```
|
||||
*/
|
||||
url: AstroSharedContext['url'];
|
||||
/**
|
||||
|
@ -2420,6 +2440,8 @@ export interface APIContext<
|
|||
*
|
||||
* Example usage:
|
||||
* ```ts
|
||||
* import type { APIContext } from "astro"
|
||||
*
|
||||
* export function getStaticPaths() {
|
||||
* return [
|
||||
* { params: { id: '0' }, props: { name: 'Sarah' } },
|
||||
|
@ -2428,14 +2450,12 @@ export interface APIContext<
|
|||
* ];
|
||||
* }
|
||||
*
|
||||
* export async function GET({ params }) {
|
||||
* return {
|
||||
* body: `Hello user ${params.id}!`,
|
||||
* }
|
||||
* export async function GET({ params }: APIContext) {
|
||||
* return new Response(`Hello user ${params.id}!`)
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* [context reference](https://docs.astro.build/en/reference/api-reference/#contextparams)
|
||||
* [Reference](https://docs.astro.build/en/reference/api-reference/#contextparams)
|
||||
*/
|
||||
params: AstroSharedContext<Props, APIParams>['params'];
|
||||
/**
|
||||
|
@ -2443,6 +2463,8 @@ export interface APIContext<
|
|||
*
|
||||
* Example usage:
|
||||
* ```ts
|
||||
* import type { APIContext } from "astro"
|
||||
*
|
||||
* export function getStaticPaths() {
|
||||
* return [
|
||||
* { params: { id: '0' }, props: { name: 'Sarah' } },
|
||||
|
@ -2451,19 +2473,17 @@ export interface APIContext<
|
|||
* ];
|
||||
* }
|
||||
*
|
||||
* export function GET({ props }) {
|
||||
* return {
|
||||
* body: `Hello ${props.name}!`,
|
||||
* }
|
||||
* export function GET({ props }: APIContext): Response {
|
||||
* return new Response(`Hello ${props.name}!`);
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* [context reference](https://docs.astro.build/en/guides/api-reference/#contextprops)
|
||||
*
|
||||
* [Reference](https://docs.astro.build/en/guides/api-reference/#contextprops)
|
||||
*/
|
||||
props: AstroSharedContext<Props, APIParams>['props'];
|
||||
/**
|
||||
* Redirect to another page. Only available in SSR builds.
|
||||
*
|
||||
* Create a response that redirects to another page.
|
||||
*
|
||||
* Example usage:
|
||||
* ```ts
|
||||
* // src/pages/secret.ts
|
||||
|
@ -2472,18 +2492,20 @@ export interface APIContext<
|
|||
* }
|
||||
* ```
|
||||
*
|
||||
* [context reference](https://docs.astro.build/en/guides/api-reference/#contextredirect)
|
||||
* [Reference](https://docs.astro.build/en/guides/api-reference/#contextredirect)
|
||||
*/
|
||||
redirect: AstroSharedContext['redirect'];
|
||||
|
||||
/**
|
||||
* Object accessed via Astro middleware.
|
||||
*
|
||||
* An object that middlewares can use to store extra information related to the request.
|
||||
*
|
||||
* It will be made available to pages as `Astro.locals`, and to endpoints as `context.locals`.
|
||||
*
|
||||
* Example usage:
|
||||
*
|
||||
*
|
||||
* ```ts
|
||||
* // src/middleware.ts
|
||||
* import {defineMiddleware} from "astro:middleware";
|
||||
* import { defineMiddleware } from "astro:middleware";
|
||||
*
|
||||
* export const onRequest = defineMiddleware((context, next) => {
|
||||
* context.locals.greeting = "Hello!";
|
||||
|
@ -2498,6 +2520,8 @@ export interface APIContext<
|
|||
* ---
|
||||
* <h1>{greeting}</h1>
|
||||
* ```
|
||||
*
|
||||
* [Reference](https://docs.astro.build/en/reference/api-reference/#contextlocals)
|
||||
*/
|
||||
locals: App.Locals;
|
||||
|
||||
|
@ -2535,12 +2559,6 @@ export interface APIContext<
|
|||
currentLocale: string | undefined;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
type Routing = {
|
||||
prefixDefaultLocale: boolean;
|
||||
strategy: 'pathname';
|
||||
};
|
||||
|
||||
export type APIRoute<
|
||||
Props extends Record<string, any> = Record<string, any>,
|
||||
APIParams extends Record<string, string | undefined> = Record<string, string | undefined>,
|
||||
|
|
|
@ -1,20 +1,51 @@
|
|||
# `core/`
|
||||
|
||||
Code that executes within the top-level Node context. Contains the main Astro logic for the `build`, `dev`, `preview`, and `sync` commands, and also manages the Vite server and SSR.
|
||||
Code that executes directly on Node (not processed by vite). Contains the main Astro logic for the `build`, `dev`, `preview`, and `sync` commands, and also manages the lifecycle of the Vite server.
|
||||
|
||||
The `core/index.ts` file is the main entry point for the `astro` package.
|
||||
The `core/index.ts` module exports the CLI commands as functions and is the main entrypoint of the `astro` package.
|
||||
```ts
|
||||
import { dev, build, preview, sync } from 'astro';
|
||||
```
|
||||
|
||||
[See CONTRIBUTING.md](../../../../CONTRIBUTING.md) for a code overview.
|
||||
|
||||
## Pipeline
|
||||
```
|
||||
Pages
|
||||
used by /
|
||||
/
|
||||
creates /
|
||||
App --------- AppPipeline AstroGlobal
|
||||
\ implements /
|
||||
\ creates /
|
||||
creates impl.\ provided to /
|
||||
vite-plugin-astro-server --------- DevPipeline ------ Pipeline ------------- RenderContext Middleware
|
||||
/ \ used by /
|
||||
/ creates \ /
|
||||
creates / implements \ /
|
||||
AstroBuilder --------- BuildPipeline APIContext
|
||||
\
|
||||
\
|
||||
used by \
|
||||
Endpoints
|
||||
```
|
||||
|
||||
The pipeline is an internal concept that describes how Astro pages are eventually created and rendered to the user.
|
||||
## `App`
|
||||
|
||||
Each pipeline has different requirements, criteria and quirks. Although, each pipeline must use the same underline functions, because
|
||||
the core of the pipeline is the same.
|
||||
## `vite-plugin-astro-server` (see `../vite-plugin-astro-server/`)
|
||||
|
||||
The core of the pipeline is rendering a generic route (page, endpoint or redirect) and returning a `Response`.
|
||||
When rendering a route, a pipeline must pass a `RenderContext` and `ComponentInstance`. The way these two information are
|
||||
computed doesn't concern the core of a pipeline. In fact, these types will be computed in different manner based on the type of pipeline.
|
||||
## `AstroBuilder`
|
||||
|
||||
Each consumer will decide how to handle a `Response`.
|
||||
## `Pipeline`
|
||||
|
||||
The pipeline is an interface representing data that stays unchanged throughout the duration of the server or build. For example: the user configuration, the list of pages and endpoints in the project, and environment-specific way of gathering scripts and styles.
|
||||
|
||||
There are 3 implementations of the pipeline:
|
||||
- `DevPipeline`: in-use during the `astro dev` CLI command. Created and used by `vite-plugin-astro-server`, and then forwarded to other internals.
|
||||
- `BuildPipeline`: in-use during the `astro build` command in `"static"` mode, and for prerendering in `"server"` and `"hybrid"` output modes. See `core/build/`.
|
||||
- `AppPipeline`: in-use during production server(less) deployments. Created and used by `App` (see `core/app/`), and then forwarded to other internals.
|
||||
|
||||
All 3 expose a common, environment-agnostic interface which is used by the rest of the internals, most notably by `RenderContext`.
|
||||
|
||||
## `RenderContext`
|
||||
|
||||
Each request is rendered using a `RenderContext`. It manages data unique to each request. For example: the parsed `URL`, internationalization data, the `locals` object, and the route that matched the request. It is responsible for executing middleware, calling endpoints, and rendering pages by gathering necessary data from a `Pipeline`.
|
||||
|
|
|
@ -1,9 +1,35 @@
|
|||
// process.env.PACKAGE_VERSION is injected when we build and publish the astro package.
|
||||
export const ASTRO_VERSION = process.env.PACKAGE_VERSION ?? 'development';
|
||||
|
||||
/**
|
||||
* The name for the header used to help rerouting behavior.
|
||||
* When set to "no", astro will NOT try to reroute an error response to the corresponding error page, which is the default behavior that can sometimes lead to loops.
|
||||
*
|
||||
* ```ts
|
||||
* const response = new Response("keep this content as-is", {
|
||||
* status: 404,
|
||||
* headers: {
|
||||
* // note that using a variable name as the key of an object needs to be wrapped in square brackets in javascript
|
||||
* // without them, the header name will be interpreted as "REROUTE_DIRECTIVE_HEADER" instead of "X-Astro-Reroute"
|
||||
* [REROUTE_DIRECTIVE_HEADER]: 'no',
|
||||
* }
|
||||
* })
|
||||
* ```
|
||||
* Alternatively...
|
||||
* ```ts
|
||||
* response.headers.set(REROUTE_DIRECTIVE_HEADER, 'no');
|
||||
* ```
|
||||
*/
|
||||
export const REROUTE_DIRECTIVE_HEADER = 'X-Astro-Reroute';
|
||||
|
||||
/**
|
||||
* The name for the header used to help i18n middleware, which only needs to act on "page" and "fallback" route types.
|
||||
*/
|
||||
export const ROUTE_TYPE_HEADER = 'X-Astro-Route-Type';
|
||||
|
||||
/**
|
||||
* The value of the `component` field of the default 404 page, which is used when there is no user-provided 404.astro page.
|
||||
*/
|
||||
export const DEFAULT_404_COMPONENT = 'astro-default-404';
|
||||
|
||||
/**
|
||||
|
@ -12,8 +38,25 @@ export const DEFAULT_404_COMPONENT = 'astro-default-404';
|
|||
*/
|
||||
export const REROUTABLE_STATUS_CODES = [404, 500];
|
||||
|
||||
/**
|
||||
* The symbol which is used as a field on the request object to store the client address.
|
||||
* The clientAddresss provided by the adapter (or the dev server) is stored on this field.
|
||||
*/
|
||||
export const clientAddressSymbol = Symbol.for('astro.clientAddress');
|
||||
|
||||
/**
|
||||
* The symbol used as a field on the request object to store the object to be made available to Astro APIs as `locals`.
|
||||
* Use judiciously, as locals are now stored within `RenderContext` by default. Tacking it onto request is no longer necessary.
|
||||
*/
|
||||
export const clientLocalsSymbol = Symbol.for('astro.locals');
|
||||
|
||||
/**
|
||||
* The symbol used as a field on the response object to keep track of streaming.
|
||||
*
|
||||
* It is set when the `<head>` element has been completely generated, rendered, and the response object has been passed onto the adapter.
|
||||
*
|
||||
* Used to provide helpful errors and warnings when headers or cookies are added during streaming, after the response has already been sent.
|
||||
*/
|
||||
export const responseSentSymbol = Symbol.for('astro.responseSent');
|
||||
|
||||
// possible extensions for markdown files
|
||||
|
|
|
@ -69,7 +69,7 @@ const ONLY_DEV_EXTERNAL = [
|
|||
'string-width',
|
||||
];
|
||||
|
||||
/** Return a common starting point for all Vite actions */
|
||||
/** Return a base vite config as a common starting point for all Vite commands. */
|
||||
export async function createVite(
|
||||
commandConfig: vite.InlineConfig,
|
||||
{ settings, logger, mode, command, fs = nodeFs }: CreateViteOptions
|
||||
|
|
|
@ -25,7 +25,11 @@ import {
|
|||
} from './errors/index.js';
|
||||
import { padMultilineString } from './util.js';
|
||||
|
||||
/** Display */
|
||||
/**
|
||||
* Prestyled messages for the CLI. Used by astro CLI commands.
|
||||
*/
|
||||
|
||||
/** Display each request being served with the path and the status code. */
|
||||
export function req({
|
||||
url,
|
||||
method,
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
import buffer from 'node:buffer';
|
||||
import crypto from 'node:crypto';
|
||||
|
||||
/**
|
||||
* Astro aims to compatible with web standards as much as possible.
|
||||
* This function adds two objects that are globally-available on most javascript runtimes but not on node 18.
|
||||
*/
|
||||
export function apply() {
|
||||
// Remove when Node 18 is dropped for Node 20
|
||||
if (!globalThis.crypto) {
|
||||
|
|
|
@ -29,6 +29,10 @@ import { sequence } from './middleware/index.js';
|
|||
import { renderRedirect } from './redirects/render.js';
|
||||
import { type Pipeline, Slots, getParams, getProps } from './render/index.js';
|
||||
|
||||
/**
|
||||
* Each request is rendered using a `RenderContext`.
|
||||
* It contains data unique to each request. It is responsible for executing middleware, calling endpoints, and rendering the page by gathering necessary data from a `Pipeline`.
|
||||
*/
|
||||
export class RenderContext {
|
||||
private constructor(
|
||||
readonly pipeline: Pipeline,
|
||||
|
|
|
@ -27,6 +27,13 @@ export interface CreateRequestOptions {
|
|||
const clientAddressSymbol = Symbol.for('astro.clientAddress');
|
||||
const clientLocalsSymbol = Symbol.for('astro.locals');
|
||||
|
||||
/**
|
||||
* Used by astro internals to create a web standard request object.
|
||||
*
|
||||
* The user of this function may provide the data in a runtime-agnostic way.
|
||||
*
|
||||
* This is used by the static build to create fake requests for prerendering, and by the dev server to convert node requests into the standard request object.
|
||||
*/
|
||||
export function createRequest({
|
||||
base,
|
||||
url,
|
||||
|
|
Loading…
Add table
Reference in a new issue