window.__VITE_REACT_SSG_HASH__ (read by every route's data loader to fetch static-loader-data-manifest-<hash>.json) is set by a plain inline <script> placed later in the document body. With script: 'async', the module script in <head> can start executing as soon as it finishes downloading, racing ahead of the HTML parser reaching that later inline script — intermittently reading the hash as undefined depending on network/cache timing, and producing a 404 on .../static-loader-data-manifest-undefined.json followed by a React hydration crash (error #418). 'defer' guarantees the module only executes after the full document, including that inline script, has been parsed — this removes the race structurally rather than just making it less likely.
39 lines
1.4 KiB
JavaScript
39 lines
1.4 KiB
JavaScript
import { defineConfig } from 'vite';
|
|
import react from '@vitejs/plugin-react';
|
|
import fs from 'node:fs';
|
|
import path from 'node:path';
|
|
import { listAllRoutePaths } from './src/data/routePaths.js';
|
|
|
|
const SITE_URL = 'https://convert.ombrora.com';
|
|
|
|
function writeSitemap(outDir) {
|
|
const paths = listAllRoutePaths();
|
|
const lastmod = new Date().toISOString().slice(0, 10);
|
|
const urls = paths
|
|
.map((p) => ` <url>\n <loc>${SITE_URL}${p}/</loc>\n <lastmod>${lastmod}</lastmod>\n </url>`)
|
|
.join('\n');
|
|
const sitemap = `<?xml version="1.0" encoding="UTF-8"?>\n<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">\n${urls}\n</urlset>\n`;
|
|
fs.writeFileSync(path.join(outDir, 'sitemap.xml'), sitemap);
|
|
}
|
|
|
|
export default defineConfig({
|
|
plugins: [react()],
|
|
server: {
|
|
proxy: {
|
|
'/api': 'http://localhost:3000',
|
|
},
|
|
},
|
|
ssgOptions: {
|
|
dirStyle: 'nested',
|
|
// 'defer' (not 'async'): the entry module reads window.__VITE_REACT_SSG_HASH__,
|
|
// which is set by a plain inline <script> placed later in the document body.
|
|
// An async module can start executing as soon as it's fetched, racing ahead
|
|
// of the parser reaching that later inline script — intermittently reading
|
|
// it as undefined depending on network/cache timing. defer guarantees the
|
|
// module only runs after the full document (including that inline script)
|
|
// has been parsed.
|
|
script: 'defer',
|
|
onFinished: writeSitemap,
|
|
},
|
|
});
|