Skip to content

Commit 2a73110

Browse files
chore: simplify fallback rendering
1 parent 671af16 commit 2a73110

3 files changed

Lines changed: 43 additions & 61 deletions

File tree

packages/fresh/src/context.ts

Lines changed: 42 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,21 @@ import { SpanStatusCode } from "@opentelemetry/api";
1212
import type { ResolvedFreshConfig } from "./config.ts";
1313
import type { BuildCache } from "./build_cache.ts";
1414
import type { LayoutConfig } from "./types.ts";
15-
import { RenderState, setRenderState } from "./runtime/server/preact_hooks.tsx";
16-
import { PARTIAL_SEARCH_PARAM } from "./constants.ts";
15+
import {
16+
FreshScripts,
17+
RenderState,
18+
setRenderState,
19+
} from "./runtime/server/preact_hooks.tsx";
20+
import { DEV_ERROR_OVERLAY_URL, PARTIAL_SEARCH_PARAM } from "./constants.ts";
1721
import { tracer } from "./otel.ts";
1822
import {
1923
type ComponentDef,
2024
isAsyncAnyComponent,
2125
type PageProps,
22-
preactRender,
2326
renderAsyncAnyComponent,
2427
renderRouteComponent,
2528
} from "./render.ts";
29+
import { renderToString } from "preact-render-to-string";
2630

2731
export interface Island {
2832
file: string;
@@ -278,22 +282,47 @@ export class Context<State> {
278282
try {
279283
setRenderState(state);
280284

281-
const inner = preactRender(
285+
let html = renderToString(
282286
vnode ?? h(Fragment, null),
283-
this,
284-
state,
285-
!hasApp,
286287
);
287288

288-
if (!hasApp) {
289-
return inner;
289+
if (hasApp) {
290+
appChild = jsxTemplate([html]);
291+
html = renderToString(appVNode);
290292
}
291293

292-
appChild = jsxTemplate([inner]);
293-
294-
const outer = preactRender(appVNode, this, state, true);
294+
if (
295+
!state.renderedHtmlBody || !state.renderedHtmlHead ||
296+
!state.renderedHtmlTag
297+
) {
298+
let fallback: VNode = jsxTemplate([html]);
299+
if (!state.renderedHtmlBody) {
300+
let scripts: VNode | null = null;
301+
302+
if (
303+
this.url.pathname !== this.config.basePath + DEV_ERROR_OVERLAY_URL
304+
) {
305+
scripts = h(FreshScripts, null) as VNode;
306+
}
307+
308+
fallback = h("body", null, fallback, scripts);
309+
}
310+
if (!state.renderedHtmlHead) {
311+
fallback = h(
312+
Fragment,
313+
null,
314+
h("head", null, h("meta", { charset: "utf-8" })),
315+
fallback,
316+
);
317+
}
318+
if (!state.renderedHtmlTag) {
319+
fallback = h("html", null, fallback);
320+
}
321+
322+
html = renderToString(fallback);
323+
}
295324

296-
return outer;
325+
return `<!DOCTYPE html>${html}`;
297326
} catch (err) {
298327
if (err instanceof Error) {
299328
span.recordException(err);

packages/fresh/src/render.ts

Lines changed: 0 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,8 @@ import {
55
type RenderableProps,
66
type VNode,
77
} from "preact";
8-
import {
9-
FreshScripts,
10-
type RenderState,
11-
} from "./runtime/server/preact_hooks.tsx";
128
import type { Context } from "./context.ts";
139
import { recordSpanError, tracer } from "./otel.ts";
14-
import { DEV_ERROR_OVERLAY_URL } from "./constants.ts";
15-
import { renderToString } from "preact-render-to-string";
16-
import { escape as escapeHtml } from "@std/html";
1710

1811
export type AsyncAnyComponent<P> = {
1912
(
@@ -56,46 +49,6 @@ export async function renderAsyncAnyComponent<Props>(
5649
);
5750
}
5851

59-
export function preactRender<State, Data>(
60-
vnode: VNode,
61-
ctx: PageProps<Data, State>,
62-
state: RenderState,
63-
renderFallback: boolean,
64-
) {
65-
let res = renderToString(vnode);
66-
67-
if (!renderFallback) return res;
68-
69-
// We require a the full outer DOM structure so that browser put
70-
// comment markers in the right place in the DOM.
71-
if (!state.renderedHtmlBody) {
72-
let scripts = "";
73-
if (ctx.url.pathname !== ctx.config.basePath + DEV_ERROR_OVERLAY_URL) {
74-
scripts = renderToString(h(FreshScripts, null));
75-
}
76-
res = `<body>${res}${scripts}</body>`;
77-
}
78-
if (!state.renderedHtmlHead) {
79-
let head = `<head><meta charset="utf-8">`;
80-
81-
const entryAssets = state.buildCache.getEntryAssets();
82-
for (let i = 0; i < entryAssets.length; i++) {
83-
const asset = entryAssets[i];
84-
85-
if (asset.endsWith(".css")) {
86-
head += `<link rel="stylesheet" href="${escapeHtml(asset)}">`;
87-
}
88-
}
89-
90-
res = `${head}</head>${res}`;
91-
}
92-
if (!state.renderedHtmlTag) {
93-
res = `<html>${res}</html>`;
94-
}
95-
96-
return `<!DOCTYPE html>${res}`;
97-
}
98-
9952
export type PageProps<Data = unknown, T = unknown> =
10053
& Pick<
10154
Context<T>,

packages/plugin-vite/tests/build_test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,7 @@ Deno.test({
192192
return (el as any).href;
193193
});
194194

195-
expect(href).toMatch(/\/assets\/client-entry-.*\.css$/);
195+
expect(href).toMatch(/\/assets\/client-entry-.*\.css(\?.*)?$/);
196196
});
197197
},
198198
);

0 commit comments

Comments
 (0)