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

@astrojs/sitemap excluded from final static output with Vercel adapter #445

Closed
1 task
dotnize opened this issue Nov 21, 2024 · 19 comments · Fixed by #508
Closed
1 task

@astrojs/sitemap excluded from final static output with Vercel adapter #445

dotnize opened this issue Nov 21, 2024 · 19 comments · Fixed by #508
Labels
- P4: important Violate documented behavior or significantly improves performance (priority) needs triage Issue needs to be triaged pkg: vercel Related to Vercel adapter (scope)

Comments

@dotnize
Copy link

dotnize commented Nov 21, 2024

Astro Info

Astro                    v5.0.0
Node                     v22.11.0
System                   Linux (x64)
Package Manager          pnpm
Output                   static
Adapter                  @astrojs/vercel
Integrations             @astrojs/mdx
                         @astrojs/sitemap

If this issue only occurs in one browser, which browser is a problem?

No response

Describe the Bug

"@astrojs/sitemap": "^3.2.1",
"@astrojs/vercel": "^8.0.0",
"astro": "^5.0.0",

output is static

Using the versions above, the sitemap-index.xml and sitemap-0.xml files are created in /dist instead of .vercel/output/static, excluding them from the final vercel deployment.

image

What's the expected result?

astro-v4 branch in the repro

"@astrojs/sitemap": "^3.2.1",
"@astrojs/vercel": "^7.8.2",
"astro": "^4.16.13",

output is hybrid

No /dist folder is created at all after building, and the sitemap is properly generated in .vercel/output/static.

[build] Rearranging server assets...
[@astrojs/sitemap] `sitemap-index.xml` created at `.vercel/output/static`

Link to Minimal Reproducible Example

https://github.com/dotnize/astro-sitemap-vercel-static

Participation

  • I am willing to submit a pull request for this issue.
@github-actions github-actions bot added the needs triage Issue needs to be triaged label Nov 21, 2024
@ematipico ematipico transferred this issue from withastro/astro Nov 21, 2024
@ematipico ematipico added - P4: important Violate documented behavior or significantly improves performance (priority) pkg: vercel Related to Vercel adapter (scope) labels Nov 21, 2024
@dotnize dotnize changed the title v5 beta - @astrojs/sitemap excluded from final static output with Vercel adapter @astrojs/sitemap excluded from final static output with Vercel adapter Dec 3, 2024
@phenomen
Copy link

phenomen commented Dec 5, 2024

I have the same issue. Sitemap does exist when I build locally but is missing when I explore build output on Vercel deployment.
static output with the new single endpoint Vercel adapter.

"@astrojs/sitemap": "^3.2.1",
"@astrojs/vercel": "8.0.0",
"astro": "^5.0.3",

@ichbinstudent
Copy link

Workaround I used: Use a hook for after the build process:

    'astro:build:done': async ({ logger }) => {
      const buildLogger = logger.fork('sitemap-copier');
      buildLogger.info("Copying xml files from dist to vercel out");
      try {
        const files = await fs.readdir('./dist/client');
        const xmlFiles = files.filter(file => 
          path.extname(file).toLowerCase() === '.xml' && 
          path.basename(file).toLowerCase().startsWith('sitemap')
        );
        buildLogger.info(xmlFiles)
        for (const file of xmlFiles) {
          const sourcePath = path.join('./dist/client', file);
          const destPath = path.join('./.vercel/output/static', file);
          await fs.copyFile(sourcePath, destPath);
        }
        buildLogger.info('All XML files copied successfully');
      } catch (error) {
        buildLogger.error('Error copying files:', error);
      }
    }

@phenomen
Copy link

phenomen commented Dec 9, 2024

Here is a full integration based on @ichbinstudent code.

  1. Create sitemap-copier.ts in your root dir.
import type { AstroIntegration } from "astro";
import { readdir, cp } from "node:fs/promises";
import * as path from "node:path";

export function sitemapCopier(): AstroIntegration {
	return {
		name: "sitemap-copier",
		hooks: {
			"astro:build:done": async ({ logger }) => {
				const buildLogger = logger.fork("sitemap-copier");
				buildLogger.info("Copying xml files from dist to vercel out");
				try {
					const files = await readdir("./dist/client");
					const xmlFiles = files.filter(
						(file) =>
							path.extname(file).toLowerCase() === ".xml" &&
							path.basename(file).toLowerCase().startsWith("sitemap")
					);
					buildLogger.info(xmlFiles.join(", "));
					for (const file of xmlFiles) {
						const sourcePath = path.join("./dist/client", file);
						const destPath = path.join("./.vercel/output/static", file);
						await cp(sourcePath, destPath);
					}
					buildLogger.info("All XML files copied successfully");
				} catch (error) {
					buildLogger.error(`Error copying files: ${error}`);
				}
			}
		}
	};
}
  1. Add it to your astro.config.js after sitemap integration:
import { sitemapCopier } from "./sitemap-copier.ts";

export default defineConfig({
        //...
	integrations: [
		sitemap({
			// your sitemap config
		}),
		sitemapCopier()
	]
});

@satinP
Copy link

satinP commented Dec 11, 2024

I'm also having this issue after upgrading to astro v5.0.4.

Using the copy workaround for now.

@bentouch-digital
Copy link

Same issue here after upgrading to astro v5

@jwoyo
Copy link

jwoyo commented Dec 14, 2024

Same problem occurs with starlight on astro 5. I was able to use @phenomen's fix (thank you!) but had to adjust the path ./dist/client to ./dist

@ematipico
Copy link
Member

This is an issue of the Vercel adapter, in combination with the sitemap integration. We haven't found a good fix yet, so moving manually the sitemap file is the best workaround

@psd-coder
Copy link

psd-coder commented Dec 26, 2024

Have the same issue. And not only with @astrojs/sitemap, but with @astrojs/partytown as well.
I found out that Vercel adapter's astro:build:done hook (where it copies all the static files) is finished before sitemap and Partytown astro:build:done hooks start, which explains why their files aren't copied.

So it seems it isn't problem of Vercel adapter particularly, but of execution order of integrations.

@arch-fan
Copy link

Hope this gets fixed soon 🙏

@arch-fan
Copy link

Have the same issue. And not only with @astrojs/sitemap, but with @astrojs/partytown as well. I found out that Vercel adapter's astro:build:done hook (where it copies all the static files) is finished before sitemap and Partytown astro:build:done hooks start, which explains why their files aren't copied.

So it seems it isn't problem of Vercel adapter particularly, but of execution order of integrations.

Well, maybe @astrojs/sitemap should be modified. In astro docs is said 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](https://docs.astro.build/en/reference/integrations-reference/#updateconfig-option) instead.

@mohdlatif
Copy link

mohdlatif commented Dec 28, 2024

I’m encountering a similar issue where I’m using some Astro compression plugins to compress JavaScript and remove comments from the code. During the build process, I noticed that the files inside dist/output do not match those in .vercel/output/static.

It seems like the Vercel build process runs before other integrations take effect, causing this discrepancy.

Thanks to the suggestions from @ichbinstudent and @phenomen , I’ve created a small script that simplifies the process of copying files from the dist folder to the .vercel/output/static directory. This solution has been effective for my case, and I hope it can help others facing the same issue:

image

  1. Create copy-files.ts in your root dir.
import type {AstroIntegration} from 'astro';
import {promises as fs} from 'fs';
import path from 'path';
import {fileURLToPath} from 'url';

// Utility function for formatted logging
function formatLog(tag: string, message: string) {
  const timestamp = new Date().toLocaleTimeString('en-US', {
    hour: '2-digit',
    hour12: false,
    minute: '2-digit',
    second: '2-digit'
  });

  // eslint-disable-next-line no-console
  console.log(
    '\n' + // Add space above
      `\x1b[90m${timestamp}\x1b[0m ` + // Gray timestamp
      `[\x1b[36m${tag}\x1b[0m] ` + // Cyan colored tag
      `${message}` + // Message
      '\n' // Add space below
  );
}

async function copyFiles(srcDir: string, destDir: string) {
  const files = await fs.readdir(srcDir);

  for (const file of files) {
    const srcPath = path.join(srcDir, file);
    const destPath = path.join(destDir, file);

    const stat = await fs.stat(srcPath);

    if (stat.isDirectory()) {
      await fs.mkdir(destPath, {recursive: true});
      await copyFiles(srcPath, destPath);
    } else {
      await fs.copyFile(srcPath, destPath);
    }
  }
}

export function CopyFilesPlugin(): AstroIntegration {
  return {
    hooks: {
      'astro:build:done': async ({dir}) => {
        formatLog('copy-files', 'Copying files to .vercel/output/static');

        const distDir = fileURLToPath(dir.href);
        const staticDir = path.resolve('.vercel/output/static');

        await fs.mkdir(staticDir, {recursive: true});
        await copyFiles(distDir, staticDir);
      }
    },
    name: 'copy-files'
  };
}
  1. Add the following code to your astro.config.js, placing it as the last step in the integrations array:
import {CopyFilesPlugin} from './copy-files.ts';

export default defineConfig({
        //...
	integrations: [
		// other integrations
		CopyFilesPlugin()
	]
});

@arch-fan
Copy link

But how do you make sure your integration runs the last one? By the declaration order?

I think Astro should implement a specific configuration for adapters. Will fix this problem.

@mohdlatif
Copy link

But how do you make sure your integration runs the last one? By the declaration order?

I think Astro should implement a specific configuration for adapters. Will fix this problem.

Yes, it's determined by the declaration order. The script hook runs after Astro finishes building, so it’s best to place CopyFilesPlugin() at the end as the last line.

TeenBiscuits added a commit to TeenBiscuits/Pasame-Codigo that referenced this issue Dec 31, 2024
@TeenBiscuits
Copy link

Thanks @mohdlatif you are amazing 🚀
I use your script in my website and now I can safetly deploy on vercel.

@lilith
Copy link

lilith commented Jan 12, 2025

Thanks for the great workaround script!
Astro really needs to fix this kind of thousand-cut bug, my site is cluttering up with workaround scripts at this point.

@dotnize
Copy link
Author

dotnize commented Jan 23, 2025

the fix in @astrojs/vercel 8.0.3 doesn't seem to work. sitemap files are still in dist/client instead of .vercel/output/static

can we have this reopened please?

EDIT: i reproduced it in the minimal repro. adding a non-static (export const prerender = false) route, either a page or API endpoint, causes the files to be generated in dist/client instead of dist/, and the sitemap files won't get copied.

13:44:44 [build] output: "server"
13:44:44 [build] directory: /home/nize/dev/playground/astro-sitemap-vercel-static/dist/
...
13:44:46 [build] Rearranging server assets...
13:44:46 [@astrojs/vercel] Bundling function ../../../../dist/server/entry.mjs
13:44:47 [@astrojs/sitemap] `sitemap-index.xml` created at `dist/client`
13:44:47 [build] Server built in 4.17s
13:44:47 [build] Complete!

in fully static mode with no hybrid routes. the fix works as expected:

13:48:22 [build] output: "static"
13:48:22 [build] directory: /home/nize/dev/playground/astro-sitemap-vercel-static/dist/
...
13:48:24 [@astrojs/sitemap] `sitemap-index.xml` created at `dist`
13:48:24 [build] 8 page(s) built in 2.61s
13:48:24 [build] Complete!

@SkyfallWasTaken
Copy link

SkyfallWasTaken commented Jan 23, 2025

Issue isn't fixed for me either :/
I also have a export const prerender = false page.

@ascorbic
Copy link
Contributor

Can you try upgrading to the latest version of @astrojs/vercel

@dotnize
Copy link
Author

dotnize commented Jan 23, 2025

#516 fixed it, thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
- P4: important Violate documented behavior or significantly improves performance (priority) needs triage Issue needs to be triaged pkg: vercel Related to Vercel adapter (scope)
Projects
None yet
Development

Successfully merging a pull request may close this issue.