diff options
author | 2023-05-03 18:19:45 +0200 | |
---|---|---|
committer | 2023-05-03 12:19:45 -0400 | |
commit | ad907196cb42f21d9540ae0d77aa742bf7adf030 (patch) | |
tree | 54e56261b5a08bb2fa021c721b0877394231ef33 /packages/integrations | |
parent | cac4a321e814fb805eb0e3ced469e25261a50885 (diff) | |
download | astro-ad907196cb42f21d9540ae0d77aa742bf7adf030.tar.gz astro-ad907196cb42f21d9540ae0d77aa742bf7adf030.tar.zst astro-ad907196cb42f21d9540ae0d77aa742bf7adf030.zip |
Sitemap: support SSR routes (#6534)
* feat(sitemap): support SSR generated routes
* feat(sitemap): add changeset for SSR support
* refactor: move logic to `astro:build:done`
* generate route to obey `trailingSlash` setting
* add logic to respect "directory" build format
* integration(sitemap): add unit test for ssr support
Diffstat (limited to 'packages/integrations')
7 files changed, 96 insertions, 18 deletions
diff --git a/packages/integrations/sitemap/package.json b/packages/integrations/sitemap/package.json index afd959a62..7c465494e 100644 --- a/packages/integrations/sitemap/package.json +++ b/packages/integrations/sitemap/package.json @@ -37,6 +37,7 @@ "zod": "^3.17.3" }, "devDependencies": { + "@astrojs/node": "workspace:*", "astro": "workspace:*", "astro-scripts": "workspace:*", "chai": "^4.3.6", diff --git a/packages/integrations/sitemap/src/index.ts b/packages/integrations/sitemap/src/index.ts index e6e45ddd1..0814ae0e1 100644 --- a/packages/integrations/sitemap/src/index.ts +++ b/packages/integrations/sitemap/src/index.ts @@ -51,6 +51,8 @@ const OUTFILE = 'sitemap-index.xml'; const createPlugin = (options?: SitemapOptions): AstroIntegration => { let config: AstroConfig; + const logger = new Logger(PKG_NAME); + return { name: PKG_NAME, @@ -59,10 +61,15 @@ const createPlugin = (options?: SitemapOptions): AstroIntegration => { config = cfg; }, - 'astro:build:done': async ({ dir, pages }) => { - const logger = new Logger(PKG_NAME); - + 'astro:build:done': async ({ dir, routes }) => { try { + if (!config.site) { + logger.warn( + 'The Sitemap integration requires the `site` astro.config option. Skipping.' + ); + return; + } + const opts = validateOptions(config.site, options); const { filter, customPages, serialize, entryLimit } = opts; @@ -78,12 +85,30 @@ const createPlugin = (options?: SitemapOptions): AstroIntegration => { return; } - let pageUrls = pages.map((p) => { - if (p.pathname !== '' && !finalSiteUrl.pathname.endsWith('/')) - finalSiteUrl.pathname += '/'; - const path = finalSiteUrl.pathname + p.pathname; - return new URL(path, finalSiteUrl).href; - }); + let pageUrls = routes.reduce<string[]>((urls, r) => { + /** + * Dynamic URLs have entries with `undefined` pathnames + */ + if (r.pathname) { + /** + * remove the initial slash from relative pathname + * because `finalSiteUrl` always has trailing slash + */ + const path = finalSiteUrl.pathname + r.generate(r.pathname).substring(1); + + let newUrl = new URL(path, finalSiteUrl).href; + + if (config.trailingSlash === 'never') { + urls.push(newUrl); + } else if (config.build.format === 'directory' && !newUrl.endsWith('/')) { + urls.push(newUrl + '/'); + } else { + urls.push(newUrl); + } + } + + return urls; + }, []); try { if (filter) { @@ -95,18 +120,11 @@ const createPlugin = (options?: SitemapOptions): AstroIntegration => { } if (customPages) { - pageUrls = [...pageUrls, ...customPages]; + pageUrls = Array.from(new Set([...pageUrls, ...customPages])); } if (pageUrls.length === 0) { - // offer suggestion for SSR users - if (config.output !== 'static') { - logger.warn( - `No pages found! We can only detect sitemap routes for "static" builds. Since you are using an SSR adapter, we recommend manually listing your sitemap routes using the "customPages" integration option.\n\nExample: \`sitemap({ customPages: ['https://example.com/route'] })\`` - ); - } else { - logger.warn(`No pages found!\n\`${OUTFILE}\` not created.`); - } + logger.warn(`No pages found!\n\`${OUTFILE}\` not created.`); return; } diff --git a/packages/integrations/sitemap/test/fixtures/ssr/astro.config.mjs b/packages/integrations/sitemap/test/fixtures/ssr/astro.config.mjs new file mode 100644 index 000000000..d914d4357 --- /dev/null +++ b/packages/integrations/sitemap/test/fixtures/ssr/astro.config.mjs @@ -0,0 +1,12 @@ +import { defineConfig } from 'astro/config'; +import sitemap from '@astrojs/sitemap'; +import nodeServer from '@astrojs/node' + +export default defineConfig({ + integrations: [sitemap()], + site: 'http://example.com', + output: 'server', + adapter: nodeServer({ + mode: "standalone" + }) +}) diff --git a/packages/integrations/sitemap/test/fixtures/ssr/package.json b/packages/integrations/sitemap/test/fixtures/ssr/package.json new file mode 100644 index 000000000..980e02e73 --- /dev/null +++ b/packages/integrations/sitemap/test/fixtures/ssr/package.json @@ -0,0 +1,9 @@ +{ + "name": "@test/sitemap-trailing-slash", + "version": "0.0.0", + "private": true, + "dependencies": { + "astro": "workspace:*", + "@astrojs/sitemap": "workspace:*" + } +} diff --git a/packages/integrations/sitemap/test/fixtures/ssr/src/pages/one.astro b/packages/integrations/sitemap/test/fixtures/ssr/src/pages/one.astro new file mode 100644 index 000000000..0c7fb90a7 --- /dev/null +++ b/packages/integrations/sitemap/test/fixtures/ssr/src/pages/one.astro @@ -0,0 +1,8 @@ +<html> + <head> + <title>One</title> + </head> + <body> + <h1>One</h1> + </body> +</html> diff --git a/packages/integrations/sitemap/test/fixtures/ssr/src/pages/two.astro b/packages/integrations/sitemap/test/fixtures/ssr/src/pages/two.astro new file mode 100644 index 000000000..e7ba9910e --- /dev/null +++ b/packages/integrations/sitemap/test/fixtures/ssr/src/pages/two.astro @@ -0,0 +1,8 @@ +<html> + <head> + <title>Two</title> + </head> + <body> + <h1>Two</h1> + </body> +</html> diff --git a/packages/integrations/sitemap/test/ssr.test.js b/packages/integrations/sitemap/test/ssr.test.js new file mode 100644 index 000000000..e6f8412d5 --- /dev/null +++ b/packages/integrations/sitemap/test/ssr.test.js @@ -0,0 +1,22 @@ +import { loadFixture, readXML } from './test-utils.js'; +import { expect } from 'chai'; + +describe('SSR support', () => { + /** @type {import('./test-utils.js').Fixture} */ + let fixture; + + before(async () => { + fixture = await loadFixture({ + root: './fixtures/ssr/', + }); + await fixture.build(); + }); + + it('SSR pages require zero config', async () => { + const data = await readXML(fixture.readFile('/client/sitemap-0.xml')); + const urls = data.urlset.url; + + expect(urls[0].loc[0]).to.equal('http://example.com/one/'); + expect(urls[1].loc[0]).to.equal('http://example.com/two/'); + }); +}); |