Skip to content

Commit b49447b

Browse files
authored
refactor: Fix source maps, error code frames, and other misc items (#149)
1 parent 22bb6af commit b49447b

File tree

1 file changed

+43
-25
lines changed

1 file changed

+43
-25
lines changed

src/prerender.ts

+43-25
Original file line numberDiff line numberDiff line change
@@ -78,14 +78,18 @@ export function PrerenderPlugin({
7878
renderTarget,
7979
additionalPrerenderRoutes,
8080
}: PrerenderPluginOptions = {}): Plugin {
81-
const preloadHelperId = "vite/preload-helper";
82-
const preloadPolyfillId = "vite/modulepreload-polyfill";
8381
let viteConfig = {} as ResolvedConfig;
8482
let userEnabledSourceMaps: boolean | undefined;
8583

8684
renderTarget ||= "body";
8785
additionalPrerenderRoutes ||= [];
8886

87+
const preloadHelperId = "vite/preload-helper";
88+
const preloadPolyfillId = "vite/modulepreload-polyfill";
89+
// PNPM, Yalc, and anything else utilizing symlinks mangle the file
90+
// path a bit so we need a minimal, fairly unique ID to check against
91+
const tmpDirId = "headless-prerender";
92+
8993
/**
9094
* From the non-external scripts in entry HTML document, find the one (if any)
9195
* that provides a `prerender` export
@@ -123,13 +127,16 @@ export function PrerenderPlugin({
123127
name: "preact:prerender",
124128
apply: "build",
125129
enforce: "post",
126-
configResolved(config) {
127-
userEnabledSourceMaps = !!config.build.sourcemap;
130+
// As of Vite 6, `sourcemap` can *only* be set in `config` and
131+
// `manualChunks` can *only* be set in `configResolved`.
132+
config(config) {
133+
userEnabledSourceMaps = !!config.build?.sourcemap;
134+
128135
// Enable sourcemaps for generating more actionable error messages
136+
config.build ??= {};
129137
config.build.sourcemap = true;
130-
131-
viteConfig = config;
132-
138+
},
139+
configResolved(config) {
133140
// With this plugin adding an additional input, Rollup/Vite tries to be smart
134141
// and extract our prerender script (which is often their main bundle) to a separate
135142
// chunk that the entry & prerender chunks can depend on. Unfortunately, this means the
@@ -157,6 +164,8 @@ export function PrerenderPlugin({
157164
return "index";
158165
}
159166
};
167+
168+
viteConfig = config;
160169
},
161170
async options(opts) {
162171
if (!opts.input) return;
@@ -263,7 +272,7 @@ export function PrerenderPlugin({
263272
viteConfig.root,
264273
"node_modules",
265274
"@preact/preset-vite",
266-
"headless-prerender",
275+
tmpDirId,
267276
);
268277
try {
269278
await fs.rm(tmpDir, { recursive: true });
@@ -279,18 +288,6 @@ export function PrerenderPlugin({
279288

280289
let prerenderEntry: OutputChunk | undefined;
281290
for (const output of Object.keys(bundle)) {
282-
// Clean up source maps if the user didn't enable them themselves
283-
if (!userEnabledSourceMaps) {
284-
if (output.endsWith(".map")) {
285-
delete bundle[output];
286-
continue;
287-
}
288-
if (output.endsWith(".js") && bundle[output].type == "chunk") {
289-
(bundle[output] as OutputChunk).code = (bundle[
290-
output
291-
] as OutputChunk).code.replace(/\n\/\/#\ssourceMappingURL=.*/, "");
292-
}
293-
}
294291
if (!output.endsWith(".js") || bundle[output].type !== "chunk")
295292
continue;
296293

@@ -316,10 +313,6 @@ export function PrerenderPlugin({
316313
);
317314
prerender = m.prerender;
318315
} catch (e) {
319-
const stack = await import("stack-trace").then(({ parse }) =>
320-
parse(e as Error).find(s => s.getFileName().includes(tmpDir)),
321-
);
322-
323316
const isReferenceError = e instanceof ReferenceError;
324317
let message = `\n
325318
${e}
@@ -335,6 +328,10 @@ export function PrerenderPlugin({
335328
}
336329
`.replace(/^\t{5}/gm, "");
337330

331+
const stack = await import("stack-trace").then(({ parse }) =>
332+
parse(e as Error).find(s => s.getFileName().includes(tmpDirId)),
333+
);
334+
338335
const sourceMapContent = prerenderEntry.map;
339336
if (stack && sourceMapContent) {
340337
await SourceMapConsumer.with(
@@ -407,7 +404,10 @@ export function PrerenderPlugin({
407404
}
408405

409406
const result = await prerender({ ssr: true, url: route.url, route });
410-
if (result == null) continue;
407+
if (result == null) {
408+
this.warn(`No result returned for route "${route.url}"`);
409+
continue;
410+
}
411411

412412
// Reset HTML doc & head data
413413
htmlDoc = htmlParse(tpl);
@@ -485,6 +485,24 @@ export function PrerenderPlugin({
485485
fileName: assetName,
486486
source: htmlDoc.toString(),
487487
});
488+
489+
// Clean up source maps if the user didn't enable them themselves
490+
if (!userEnabledSourceMaps) {
491+
for (const output of Object.keys(bundle)) {
492+
if (output.endsWith(".map")) {
493+
delete bundle[output];
494+
continue;
495+
}
496+
if (output.endsWith(".js")) {
497+
const codeOrSource =
498+
bundle[output].type == "chunk" ? "code" : "source";
499+
// @ts-ignore
500+
bundle[output][codeOrSource] = bundle[output][
501+
codeOrSource
502+
].replace(/\n\/\/#\ssourceMappingURL=.*/, "");
503+
}
504+
}
505+
}
488506
}
489507
},
490508
};

0 commit comments

Comments
 (0)