-
-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
docs: Document sitemap extension (#41)
- Loading branch information
Showing
4 changed files
with
211 additions
and
46 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,193 @@ | ||
--- | ||
title: Sitemap Extensions | ||
description: An unofficial extension of the official @astrojs/sitemap integration. | ||
packageName: '@inox-tools/sitemap-ext' | ||
--- | ||
|
||
An unofficial extension of the official [`@astrojs/sitemap`](https://docs.astro.build/en/guides/integrations-guide/sitemap/) integration that allows: | ||
|
||
- Each route to self-declare whether they should be included in the sitemap. | ||
- Including only a subset of pages rendered from a dynamic route in the sitemap. | ||
- On-demand (SSR) routes to include themselves in the sitemap, or some of their known pages if they are dynamic. | ||
|
||
The goal of this extension is to provide higher-level functionality and configuration over the official integration. **These extensions are not maintained nor supported by the Astro team.** If some or all of these extensions prove themselves as valuable additions for the users they might be proposed and adopted into the official integration, in that case they would continue to work in this package, but as a thin wrapper or just a re-export from the official package. | ||
|
||
## Installation | ||
|
||
To install this integration you just need to replace the import from the official `@astrojs/sitemap` integration with `@inox-tools/sitemap-ext`. | ||
|
||
```ts title="astro.config.mjs" del={1} add={2} | ||
import sitemap from '@astrojs/sitemap'; | ||
import sitemap from '@inox-tools/sitemap-ext'; | ||
|
||
export default defineConfig({ | ||
integration: [sitemap()], | ||
}); | ||
``` | ||
|
||
This integration accepts all the [options from `@astrojs/sitemap`](https://docs.astro.build/en/guides/integrations-guide/sitemap/#configuration), except for the `filter` function that is replaced by the [per-route configuration](#per-route-configuration). | ||
|
||
### `includeByDefault` | ||
|
||
**Type:** `boolean` | ||
**Default:** `false` | ||
|
||
Whether pre-rendered pages that do not explicitly define their presence in the sitemap should be included. | ||
|
||
On-demand routes must always explicitly opt-in to being in the sitemap. | ||
|
||
## Per-Route configuration | ||
|
||
Each of your routes can define how they should be included in your sitemap by importing the module `sitemap-ext:config`. | ||
|
||
### Full opt-in/out | ||
|
||
For a page to fully opt-in or opt-out of being in the sitemap you can pass a boolean value to the imported module: | ||
|
||
```astro | ||
--- | ||
import sitemap from 'sitemap-ext:config'; | ||
sitemap(true); // opt-in | ||
sitemap(true); // opt-out | ||
--- | ||
``` | ||
|
||
In this case all pages created from the route will follow the given configuration. | ||
|
||
:::caution | ||
This applies for all pre-rendered routes and to on-demand _static_ routes (routes that don't have dynamic parameters in their path). | ||
|
||
On-demand dynamic routes, like `/[...slug].astro`, can't use the full opt-in since the official sitemap integration that is used under the hood must generate the sitemap statically. | ||
::: | ||
|
||
### Configuration callback | ||
|
||
For non-trivial scenarios, you can provide a hook function to define how a route should be included in the sitemap. | ||
This hook function will be called during build-time only and will be given callbacks to inform the decisions. It has the following signature: | ||
|
||
```ts | ||
type ConfigHook = (callbacks: { | ||
addToSitemap: (routeParams?: Record<string, string | undefined>[]) => void; | ||
removeFromSitemap: (routeParams?: Record<string, string | undefined>[]) => void; | ||
setSitemap: ( | ||
routeParams: Array<{ sitemap?: boolean; params: Record<string, string | undefined> }> | ||
) => void; | ||
}) => Promise<void> | void; | ||
``` | ||
|
||
As noted by the type, the given hook function can be async, which means you can load remote information. | ||
|
||
```astro | ||
--- | ||
import sitemap from 'sitemap-ext:config'; | ||
sitemap(async ({ addToSitemap, removeFromSitemap }) => { | ||
const shouldBeIncluded = await fetchThisConfigFromRemote(); | ||
if (shouldBeIncluded) { | ||
addToSitemap(); | ||
} else { | ||
removeFromSitemap(); | ||
} | ||
}); | ||
--- | ||
``` | ||
|
||
Not calling any of the given configuration callbacks means the route will follow what is defined by the global [`includeByDefault` option](#includebydefault) | ||
|
||
#### `addToSitemap` / `removeFromSitemap` | ||
|
||
Calling these configuration callbacks without any argument has the same meaning as the [full opt in/out](#full-opt-inout) using the boolean values. | ||
|
||
These functions also allow passing a list of parameter maps in the argument, these parameter maps are the same as the [`params` field in Astro's `getStaticPaths`](https://docs.astro.build/en/reference/api-reference/#params). | ||
|
||
On a static route this argument is ignored. On a dynamic route, this argument is used to replace the dynamic segments and add the resulting URLs to the sitemap. This means you can add some pages generated by an Astro route to the sitemap while keeping others out of it. | ||
|
||
```astro title="src/pages/[locale]/[postId].astro" | ||
--- | ||
import { getCollection } from 'astro:content'; | ||
import sitemap from 'sitemap-ext:config'; | ||
sitemap(async ({ addToSitemap }) => { | ||
const blogPosts = await getCollection('posts'); | ||
addToSitemap( | ||
blogPosts.map((post) => ({ | ||
locale: post.data.locale, | ||
postId: post.data.id, | ||
})) | ||
); | ||
}); | ||
--- | ||
``` | ||
|
||
#### `setSitemap` | ||
|
||
This function receives an array of parameter maps with a boolean to indicate whether each of those parameters describe a route that should be included or excluded from the sitemap. | ||
|
||
If the boolean field is not given it defaults to the global [`includeByDefault` option](#includebydefault) | ||
|
||
Calling this function from a static route does nothing. | ||
|
||
```astro title="src/pages/[locale]/[postId].astro" | ||
--- | ||
import { getCollection } from 'astro:content'; | ||
import sitemap from 'sitemap-ext:config'; | ||
sitemap(async ({ setSitemap }) => { | ||
const blogPosts = await getCollection('posts'); | ||
setSitemap( | ||
blogPosts.map((post) => ({ | ||
params: { | ||
locale: post.data.locale, | ||
postId: post.data.id, | ||
}, | ||
sitemap: post.data.includeInSitemap, | ||
})) | ||
); | ||
}); | ||
--- | ||
``` | ||
|
||
## Interaction with Astro features | ||
|
||
### `getStaticPaths` | ||
|
||
To avoid writing the same logic twice you can call the sitemap configuration function from inside `getStaticPaths`. This allows you to compute the `params` for your routes only once. | ||
|
||
```astro title="src/pages/[locale]/[postId].astro" | ||
--- | ||
import { getCollection } from 'astro:content'; | ||
import sitemap from 'sitemap-ext:config'; | ||
export async function getStaticPaths() { | ||
const blogPosts = await getCollection('posts'); | ||
const postParams = blogPosts.map((post) => ({ | ||
params: { | ||
locale: post.data.locale, | ||
postId: post.data.id, | ||
}, | ||
props: { post }, // for Astro.props | ||
sitemap: post.data.includeInSitemap, | ||
})); | ||
sitemap(({ setSitemap }) => setSitemap(postParams)); | ||
return postParams; | ||
} | ||
--- | ||
``` | ||
|
||
### On-demand rendered pages (SSR) | ||
|
||
The official sitemap integration doesn't have built-in support for SSR pages, requiring you to re-declare in your configuration all the URLs for server-rendered content that you want included in your sitemap. | ||
|
||
Using this extension, on-demand routes can opt into being included in the sitemap. SSR pages on static routes can use the [boolean option](#full-opt-inout) to add themselves to the sitemap. Dynamic routes can only add the pages that are known at build time. This can be useful in many scenarios: | ||
|
||
- When you can generate the content for any matching URL, but some of them are well-known. | ||
- When providing [self-healing URLs](https://medium.com/@vishalkamath853/self-healing-urls-eb66756a9c62) to support renaming your slugs over time. | ||
- When your content can change per-request, but not the URLs. |