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

Open
1 task
dotnize opened this issue Nov 21, 2024 · 14 comments
Open
1 task
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.

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

No branches or pull requests