Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(next): routes resolved hook #10077

Merged
merged 8 commits into from
Nov 22, 2024
40 changes: 40 additions & 0 deletions src/content/docs/en/guides/upgrade-to/v5.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -361,6 +361,46 @@ export default function createIntegration() {

<ReadMore>Learn more about [the Adapter API](/en/reference/adapter-reference/) for building adapter integrations.</ReadMore>

### Deprecated: `routes` on `astro:build:done` hook (Integration API)

<SourcePR number="12329" title="feat(next): astro:routes:resolved"/>

In Astro v4.x, you could only get routes in an integration from the `astro:build:done` hook.
florian-lefebvre marked this conversation as resolved.
Show resolved Hide resolved

Astro v5.0 deprecates the `routes` array passed to this hook. Instead, it exposes a new `astro:routes:resolved` hook that runs before `astro:config:done`, and whenever a route changes in development. It has all the same properties of the deprecated `routes` list, except `distURL` which is only available during build.

#### What should I do?

Remove any instance of `routes` passed to `astro:build:done` and replace it with the new `astro:routes:resolved` hook. Access `distURL` on the newly exposed `assets` map:

```js title="my-integration.mjs" ins={2,6-8,11,13-18} del={10}
const integration = () => {
let routes
return {
name: 'my-integration',
hooks: {
'astro:routes:resolved': (params) => {
routes = params.routes
},
'astro:build:done': ({
routes
assets
}) => {
for (const route of routes) {
const distURL = assets.get(route.pattern)
if (distURL) {
Object.assign(route, { distURL })
}
}
console.log(routes)
}
}
}
}
```

<ReadMore>Learn more about [the Integration API](/en/reference/integrations-reference/) for building integrations.</ReadMore>
florian-lefebvre marked this conversation as resolved.
Show resolved Hide resolved

## Removed

The following features have now been entirely removed from the code base and can no longer be used. Some of these features may have continued to work in your project even after deprecation. Others may have silently had no effect.
Expand Down
167 changes: 164 additions & 3 deletions src/content/docs/en/reference/integrations-reference.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ interface AstroIntegration {
createCodegenDir: () => URL;
logger: AstroIntegrationLogger;
}) => void | Promise<void>;
'astro:routes:resolved'?: (options: {
routes: IntegrationResolvedRoute[];
logger: AstroIntegrationLogger;
}) => void | Promise<void>;
'astro:config:done'?: (options: {
config: AstroConfig;
setAdapter: (adapter: AstroAdapter) => void;
Expand All @@ -62,7 +66,13 @@ interface AstroIntegration {
entryPoints: Map<IntegrationRouteData, URL>;
logger: AstroIntegrationLogger;
}) => void | Promise<void>;
'astro:build:done'?: (options: { dir: URL; routes: IntegrationRouteData[]; logger: AstroIntegrationLogger; }) => void | Promise<void>;
'astro:build:done'?: (options: {
dir: URL;
/** @deprecated Use the `assets` map and the new `astro:routes:resolved` hook */
routes: IntegrationRouteData[];
assets: Map<string, URL[]>;
logger: AstroIntegrationLogger;
}) => void | Promise<void>;

// ... any custom hooks from integrations
};
Expand Down Expand Up @@ -452,10 +462,143 @@ const integration = {
}
```

### `astro:config:done`
### `astro:routes:resolved`

<Since v="5.0.0" />

**Previous hook:** [`astro:config:setup`](#astroconfigsetup)

**Next hook:** [`astro:config:done`](#astroconfigdone)

**When:** In `astro dev`, it also runs if a file based route changes (added/removed/updated).

**Why:** To access routes and their metadata

```js
'astro:routes:resolved'?: (options: {
routes: IntegrationResolvedRoute[];
logger: AstroIntegrationLogger;
}) => void | Promise<void>;
```

#### `routes` option

**Type:** [`IntegrationResolvedRoute[]`](#integrationresolvedroute-type-reference)

A list of all routes alongside their associated metadata.
florian-lefebvre marked this conversation as resolved.
Show resolved Hide resolved

You can reference the full `IntegrationResolvedRoute` type below, but the most common properties are:

- `entrypoint` - the input file path relative to the project root
- `pathname` - the output file URL (undefined for routes using `[dynamic]` and `[...spread]` params)
florian-lefebvre marked this conversation as resolved.
Show resolved Hide resolved

##### `IntegrationResolvedRoute` type reference

```ts
interface IntegrationResolvedRoute {
/**
* The current **pattern** of the route. For example:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* The current **pattern** of the route. For example:
* The current **pattern** of the route, the path relative to the `src/pages/` directory and without a file extension. For example:

This appears to be the pattern, right? Would you change this description?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All those jsdoc come directly from core, and are also in astro:build:done. So do you prefer not to update the jsdoc on that page at all, or update them in core and then reflect the changes here?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, OK. How important is it that these are kept identical to core? This is public facing docs, and one could argue should be written like docs.

(I was even thinking, this is a LOT of documenting going on inside a code sample. Why aren't we writing normal docs here?)

In that case, I'm OK to merge exactly what's already matching, but then think about at some point in the future this page becomes an actual docs page, not just copy paste of whatever you've written in code that I have no control over the quality of. 😅

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I think that's a good idea 👍

* - `src/pages/index.astro` has a pattern of `/`
* - `src/pages/blog/[...slug].astro` has a pattern of `/blog/[...slug]`
* - `src/pages/site/[blog]/[...slug].astro` has a pattern of `/site/[blog]/[...slug]`
*/
pattern: RouteData['route'];

/**
*
* regex used for matching an input URL against a requested route
* ex. "[fruit]/about.astro" will generate the pattern: /^\/([^/]+?)\/about\/?$/
* where pattern.test("banana/about") is "true"
*
* ## Example
*
* ```js
* if (route.pattern.test('/blog')) {
* // do something
* }
* ```
*/
patternRegex: RouteData['pattern'];

/**
* Source component URL
*/
entrypoint: RouteData['component'];

/**
* Whether the route is prerendered or not
*/
isPrerendered: RouteData['prerender'];

/**
* The {@link IntegrationResolvedRoute} to redirect to. It's present when `IntegrationResolvedRoute.type` is `redirect`.
florian-lefebvre marked this conversation as resolved.
Show resolved Hide resolved
*/
redirectRoute?: IntegrationResolvedRoute;

/**
* @param {any} data The optional parameters of the route
*
* @description
* A function that accepts a list of params, interpolates them with the route pattern, and returns the path name of the route.
*
* ## Example
*
* For a route such as `/blog/[...id].astro`, the `generate` function would return something like this:
florian-lefebvre marked this conversation as resolved.
Show resolved Hide resolved
*
* ```js
* console.log(generate({ id: 'presentation' })) // will log `/blog/presentation`
* ```
*/
generate: (data?: any) => string;

/**
* Dynamic and spread route params
florian-lefebvre marked this conversation as resolved.
Show resolved Hide resolved
* ex. "/pages/[lang]/[...slug].astro" will output the params ['lang', '...slug']
*/
params: string[];

/**
* Output URL pathname where this route will be served
florian-lefebvre marked this conversation as resolved.
Show resolved Hide resolved
* note: will be undefined for [dynamic] and [...spread] routes
*/
pathname?: string;

/**
* Similar to the "params" field, but with more associated metadata. For example, for `/site/[blog]/[...slug].astro`, the segments are:
florian-lefebvre marked this conversation as resolved.
Show resolved Hide resolved
*
* 1. `{ content: 'site', dynamic: false, spread: false }`
* 2. `{ content: 'blog', dynamic: true, spread: false }`
* 3. `{ content: '...slug', dynamic: true, spread: true }`
*/
segments: RoutePart[][];

/**
*
* The type of the route. It can be:
* - `page`: a route that lives in the file system, usually an Astro component
* - `endpoint`: a route that lives in the file system, usually a JS file that exposes endpoints methods
* - `redirect`: a route points to another route that lives in the file system
florian-lefebvre marked this conversation as resolved.
Show resolved Hide resolved
* - `fallback`: a route that doesn't exist in the file system that needs to be handled with other means, usually the middleware
florian-lefebvre marked this conversation as resolved.
Show resolved Hide resolved
*/
type: RouteType;

/**
* The route to redirect to. It holds information regarding the status code and its destination.
*/
redirect?: RedirectConfig;

/**
* Whether the route comes from Astro core, an integration or the user's project
florian-lefebvre marked this conversation as resolved.
Show resolved Hide resolved
*/
origin: 'internal' | 'external' | 'project';
}
```


### `astro:config:done`

**Previous hook:** [`astro:config:setup`](#astroroutesresolved)

**Next hook:** [`astro:server:setup`](#astroserversetup) when running in "dev" mode, or [`astro:build:start`](#astrobuildstart) during production builds

**When:** After the Astro config has resolved and other integrations have run their `astro:config:setup` hooks.
Expand Down Expand Up @@ -702,7 +845,13 @@ The address, family and port number supplied by the [Node.js Net module](https:/
**Why:** To access generated routes and assets for extension (ex. copy content into the generated `/assets` directory). If you plan to transform generated assets, we recommend exploring the [Vite Plugin API](https://vite.dev/guide/api-plugin.html) and [configuring via `astro:config:setup`](#updateconfig-option) instead.

```js
'astro:build:done'?: (options: { dir: URL; routes: IntegrationRouteData[], pages: { pathname: string }[] }) => void | Promise<void>;
'astro:build:done'?: (options: {
dir: URL;
/** @deprecated Use the `assets` map and the new `astro:routes:resolved` hook */
routes: IntegrationRouteData[];
assets: Map<string, URL[]>;
logger: AstroIntegrationLogger;
}) => void | Promise<void>;
```

#### `dir` option
Expand Down Expand Up @@ -731,6 +880,10 @@ export default function myIntegration() {

#### `routes` option

:::caution
This property is deprecated since v5.0. Check the [migration guide](/en/guides/upgrade-to/v5/#deprecated-routes-on-astrobuilddone-hook-integration-api).
:::

**Type:** [`IntegrationRouteData[]`](#integrationroutedata-type-reference)

A list of all generated routes alongside their associated metadata.
Expand Down Expand Up @@ -809,6 +962,14 @@ interface IntegrationRouteData {
}
```

#### `assets` option

<Since v="5.0.0" />

**Type:** `Map<string, URL[]>`

Contains URLs to output files paths, grouped by [`IntegrationResolvedRoute`](#integrationresolvedroute-type-reference) `pattern` property.
florian-lefebvre marked this conversation as resolved.
Show resolved Hide resolved

#### `pages` option

**Type:** `{ pathname: string }[]`
Expand Down
Loading