Skip to content

Commit

Permalink
chore(astro): Optimize stream modification (#3673)
Browse files Browse the repository at this point in the history
Co-authored-by: panteliselef <[email protected]>
  • Loading branch information
wobsoriano and panteliselef authored Jul 9, 2024
1 parent bb3c625 commit 69deca0
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 32 deletions.
5 changes: 5 additions & 0 deletions .changeset/olive-foxes-own.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@clerk/astro": patch
---

Improve stream processing performance
68 changes: 36 additions & 32 deletions packages/astro/src/server/clerk-middleware.ts
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,16 @@ function decorateAstroLocal(req: Request, context: APIContext, requestState: Req
context.locals.currentUser = createCurrentUser(req, context);
}

/**
* Find the index of the closing head tag in the chunk.
*
* Note: This implementation uses a simple approach that works for most of our
* current use cases.
*/
function findClosingHeadTagIndex(chunk: Uint8Array, endHeadTag: Uint8Array) {
return chunk.findIndex((_, i) => endHeadTag.every((value, j) => value === chunk[i + j]));
}

async function decorateRequest(
locals: APIContext['locals'],
res: Response,
Expand All @@ -245,48 +255,42 @@ async function decorateRequest(
* without sucrificing DX and having developers wrap each page with a Layout that would handle this.
*/
if (res.headers.get('content-type') === 'text/html') {
const reader = res.body?.getReader();
const stream = new ReadableStream({
async start(controller) {
let { value, done } = await reader!.read();
const encoder = new TextEncoder();
const decoder = new TextDecoder();
while (!done) {
const decodedValue = decoder.decode(value);
const encoder = new TextEncoder();
const closingHeadTag = encoder.encode('</head>');
const clerkAstroData = encoder.encode(
`<script id="__CLERK_ASTRO_DATA__" type="application/json">${JSON.stringify(locals.auth())}</script>\n`,
);
const clerkSafeEnvVariables = encoder.encode(
`<script id="__CLERK_ASTRO_SAFE_VARS__" type="application/json">${JSON.stringify(getClientSafeEnv(locals))}</script>\n`,
);
const hotloadScript = encoder.encode(buildClerkHotloadScript(locals));

const stream = res.body!.pipeThrough(
new TransformStream({
transform(chunk, controller) {
const index = findClosingHeadTagIndex(chunk, closingHeadTag);
const isClosingHeadTagFound = index !== -1;

/**
* Hijack html response to position `__CLERK_ASTRO_DATA__` before the closing `head` html tag
*/
if (decodedValue.includes('</head>')) {
const [p1, p2] = decodedValue.split('</head>');
controller.enqueue(encoder.encode(p1));
controller.enqueue(
encoder.encode(
`<script id="__CLERK_ASTRO_DATA__" type="application/json">${JSON.stringify(locals.auth())}</script>\n`,
),
);

controller.enqueue(
encoder.encode(
`<script id="__CLERK_ASTRO_SAFE_VARS__" type="application/json">${JSON.stringify(getClientSafeEnv(locals))}</script>\n`,
),
);
if (isClosingHeadTagFound) {
controller.enqueue(chunk.slice(0, index));
controller.enqueue(clerkAstroData);
controller.enqueue(clerkSafeEnvVariables);

if (__HOTLOAD__) {
controller.enqueue(encoder.encode(buildClerkHotloadScript(locals)));
controller.enqueue(hotloadScript);
}

controller.enqueue(encoder.encode('</head>'));
controller.enqueue(encoder.encode(p2));
controller.enqueue(closingHeadTag);
controller.enqueue(chunk.slice(index + closingHeadTag.length));
} else {
controller.enqueue(value);
controller.enqueue(chunk);
}

({ value, done } = await reader!.read());
}
controller.close();
},
});
},
}),
);

const modifiedResponse = new Response(stream, {
status: res.status,
Expand Down

0 comments on commit 69deca0

Please sign in to comment.