Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 15 additions & 10 deletions bifrost-fastify/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,13 +83,17 @@ export const viteProxyPlugin: FastifyPluginAsync<
return reply.code(404).type("text/html").send("Not Found");
}

const { pipe, statusCode, headers } = httpResponse;
const stream = new PassThrough();
pipe(stream);
return reply
.status(statusCode)
.headers(Object.fromEntries(headers))
.send(stream);
const { statusCode, headers, getBody } = httpResponse;
return (
reply
.status(statusCode)
.headers(Object.fromEntries(headers))
// This disables any possibility of real streaming. To re-enable streaming we should adopt vike-photon and rewrite wrapped proxy as a Vike middleware.
// Why not pipe? Because Vike gives us `pipe` which sends data into a Writable, but Fastify's reply.send only accepts a ReadableStream. Passthrough can convert but causes race conditions
// We would have to pipe into reply.raw, but that skips Fastify's reply handling (like onSend hooks)
// Photon/universal-middleware solves this with some hacks around reply.body
.send(await getBody())
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this was needed because we were getting "write to stream after end" issues with the streaming. it also seems to improve response time

);
}
await fastify.register(accepts);
fastify.decorateRequest("bifrostPageId", null);
Expand Down Expand Up @@ -122,6 +126,10 @@ export const viteProxyPlugin: FastifyPluginAsync<
req.vikePageContext = pageContext;

const proxyMode = pageContext.config?.proxyMode;
if (!proxyMode) {
req.log.info(`bifrost: rendering page ${pageContext.pageId}`);
return replyWithPage(reply, pageContext);
}

switch (proxyMode) {
case "passthru": {
Expand Down Expand Up @@ -163,9 +171,6 @@ export const viteProxyPlugin: FastifyPluginAsync<
}
break;
}
default:
req.log.info(`bifrost: rendering page ${pageContext.pageId}`);
return replyWithPage(reply, pageContext);
}

if (pageContext.urlParsed) {
Expand Down
2 changes: 1 addition & 1 deletion bifrost-fastify/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
"peerDependencies": {
"@alignable/bifrost": "1.0.15",
"fastify": "^5.0.0",
"vike": ">=0.4.248",
"vike": ">=0.4.251",
"vite": ">=6"
},
"devDependencies": {
Expand Down
4 changes: 2 additions & 2 deletions bifrost/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
"peerDependencies": {
"react": ">=18",
"typescript": ">=4.7",
"vike": ">=0.4.248",
"vike": ">=0.4.251",
"vike-react": ">=0.6.11"
},
"devDependencies": {
Expand All @@ -60,7 +60,7 @@
"typescript": "^5.0.4",
"vike-react": "0.6.11",
"vite": "^6.3.5",
"vike": "0.4.250",
"vike": "0.4.252",
"cross-env": "^7.0.3"
}
}
2 changes: 2 additions & 0 deletions bifrost/renderer/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ export default {
case "wrapped":
return {
Page: "import:@alignable/bifrost/__internal/renderer/wrapped/Page:default" as any,
onRenderHtml:
"import:@alignable/bifrost/__internal/renderer/wrapped/onRenderHtml:default",
onBeforeRenderHtml:
"import:@alignable/bifrost/__internal/renderer/wrapped/onBeforeRenderHtml:default",
onBeforeRender:
Expand Down
12 changes: 12 additions & 0 deletions bifrost/renderer/wrapped/onRenderHtml.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { dangerouslySkipEscape } from "vike/server";
// @ts-ignore vike-react import typescript is wrong
import { onRenderHtml as vikeReactRender } from "vike-react/__internal/integration/onRenderHtml";
import { PageContextServer } from "vike/types";

const emptydocument = dangerouslySkipEscape("");
export default async function onRenderHtml(pageContext: PageContextServer) {
if (pageContext._wrappedServerOnly) {
return await vikeReactRender(pageContext);
}
return { documentHtml: emptydocument };
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in wrapped mode we render twice. once for routing, then again after we get data from rails. this adds fast-path for the initial routing render.

maybe in the future vike could give us an API for routing w/o rendering

}
22 changes: 11 additions & 11 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion tests/vite/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
"@vitejs/plugin-react": "^4.7.0",
"fastify": "^5.6.2",
"uuid": "^9.0.0",
"vike": "0.4.250",
"vike": "0.4.252",
"vike-react": "^0.6.10",
"vite": "^6.3.5"
},
Expand Down
28 changes: 15 additions & 13 deletions tests/vite/pages/custom-vite/+Page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,24 @@ import { usePageContext } from "vike-react/usePageContext";

export default function Page() {
const { urlParsed } = usePageContext();
const pageData = urlParsed.search["page"];
return (
<>
<h1>vite is here</h1>
{(JSON.parse(urlParsed.search["page"]) as PageDataOk)?.links?.map(
(link) =>
"title" in link && (
<a
href={`/${link.endpoint || "custom"}?page=${encodeURI(
JSON.stringify(link)
)}`}
key={link.title}
>
{link.title}
</a>
)
)}
{pageData &&
(JSON.parse(pageData) as PageDataOk)?.links?.map(
(link) =>
"title" in link && (
<a
href={`/${link.endpoint || "custom"}?page=${encodeURI(
JSON.stringify(link)
)}`}
key={link.title}
>
{link.title}
</a>
)
)}
</>
);
}