-
Notifications
You must be signed in to change notification settings - Fork 87
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix: use version of htmlrewriter which does not make use of asyncify,…
… which looks to have a potential memory leak under high load (#2721) * fix: use version of htmlrewriter which does not make use of asyncify, which looks to have a potential memory leak under high load we noticed the memory issue with Netlify's CSP plugin which used the same htmlrewriter library. We've built a new htmlrewriter library which uses the latest version of lol-html and removes the ability to use async-handlers, which is what required asyncify to be included. * chore: vendor updated htmlrewriter * fix: update remaining htmlrewriter import * fix: workaround deno vendor limitation (not pulling static wasm files) * fix: inline htmlrewriter wasm blob to workaround bundling problems * Update tools/build.js Co-authored-by: Philippe Serhal <[email protected]> --------- Co-authored-by: jake champion <[email protected]> Co-authored-by: Philippe Serhal <[email protected]>
- Loading branch information
1 parent
6b56128
commit 4d7ad97
Showing
6 changed files
with
44 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,6 @@ | ||
import type { Context } from '@netlify/edge-functions' | ||
|
||
import { ElementHandlers } from '../vendor/deno.land/x/[email protected]/index.ts' | ||
import type { ElementHandlers } from '../vendor/deno.land/x/[email protected]/src/index.ts' | ||
|
||
type NextDataTransform = <T>(data: T) => T | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,8 @@ | ||
import type { Context } from '@netlify/edge-functions' | ||
import { HTMLRewriter } from '../vendor/deno.land/x/[email protected]/index.ts' | ||
import { | ||
HTMLRewriter, | ||
type TextChunk, | ||
} from '../vendor/deno.land/x/[email protected]/src/index.ts' | ||
|
||
import { updateModifiedHeaders } from './headers.ts' | ||
import type { StructuredLogger } from './logging.ts' | ||
|
@@ -79,7 +82,7 @@ export const buildResponse = async ({ | |
|
||
if (response.dataTransforms.length > 0) { | ||
rewriter.on('script[id="__NEXT_DATA__"]', { | ||
text(textChunk) { | ||
text(textChunk: TextChunk) { | ||
// Grab all the chunks in the Next data script tag | ||
buffer += textChunk.text | ||
if (textChunk.lastInTextNode) { | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,6 +12,6 @@ import 'https://deno.land/[email protected]/node/util.ts' | |
import 'https://deno.land/[email protected]/path/mod.ts' | ||
|
||
import 'https://deno.land/x/[email protected]/index.ts' | ||
import 'https://deno.land/x/[email protected]/index.ts' | ||
import 'https://deno.land/x/[email protected]/src/index.ts' | ||
|
||
import 'https://v1-7-0--edge-utils.netlify.app/logger/mod.ts' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -85,13 +85,27 @@ const writeHandlerFile = async (ctx: PluginContext, { matchers, name }: NextDefi | |
JSON.stringify(minimalNextConfig), | ||
) | ||
|
||
const htmlRewriterWasm = await readFile( | ||
join( | ||
ctx.pluginDir, | ||
'edge-runtime/vendor/deno.land/x/[email protected]/pkg/htmlrewriter_bg.wasm', | ||
), | ||
) | ||
|
||
// Writing the function entry file. It wraps the middleware code with the | ||
// compatibility layer mentioned above. | ||
await writeFile( | ||
join(handlerDirectory, `${handlerName}.js`), | ||
` | ||
import { decode as _base64Decode } from './edge-runtime/vendor/deno.land/[email protected]/encoding/base64.ts'; | ||
import { init as htmlRewriterInit } from './edge-runtime/vendor/deno.land/x/[email protected]/src/index.ts' | ||
import {handleMiddleware} from './edge-runtime/middleware.ts'; | ||
import handler from './server/${name}.js'; | ||
await htmlRewriterInit({ module_or_path: _base64Decode(${JSON.stringify( | ||
htmlRewriterWasm.toString('base64'), | ||
)}).buffer }); | ||
export default (req, context) => handleMiddleware(req, context, handler); | ||
`, | ||
) | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,8 @@ | ||
import { createWriteStream } from 'node:fs' | ||
import { cp, rm } from 'node:fs/promises' | ||
import { resolve, join } from 'node:path' | ||
import { join, resolve } from 'node:path' | ||
import { Readable } from 'stream' | ||
import { finished } from 'stream/promises' | ||
|
||
import { build, context } from 'esbuild' | ||
import { execaCommand } from 'execa' | ||
|
@@ -94,6 +97,23 @@ async function vendorDeno() { | |
console.log(`📦 Vendoring Deno modules into '${vendorDest}'...`) | ||
|
||
await execaCommand(`deno vendor ${vendorSource} --output=${vendorDest} --force`) | ||
|
||
// htmlrewriter contains wasm files and those don't currently work great with vendoring | ||
// see https://github.com/denoland/deno/issues/14123 | ||
// to workaround this we copy the wasm files manually | ||
const filesToDownload = ['https://deno.land/x/[email protected]/pkg/htmlrewriter_bg.wasm'] | ||
await Promise.all( | ||
filesToDownload.map(async (urlString) => { | ||
const url = new URL(urlString) | ||
|
||
const destination = join(vendorDest, url.hostname, url.pathname) | ||
|
||
const res = await fetch(url) | ||
if (!res.ok) throw new Error('Failed to fetch .wasm file to vendor', { cause: err }) | ||
const fileStream = createWriteStream(destination, { flags: 'wx' }) | ||
await finished(Readable.fromWeb(res.body).pipe(fileStream)) | ||
}), | ||
) | ||
} | ||
|
||
const args = new Set(process.argv.slice(2)) | ||
|