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
5 changes: 5 additions & 0 deletions .changeset/quiet-bees-copy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@sveltejs/adapter-netlify': patch
---

fix: support bare Node built-in imports and `.wasm`/font files in edge functions
18 changes: 15 additions & 3 deletions packages/adapter-netlify/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -402,7 +402,9 @@ function to_import_specifier(path) {

/** @satisfies {import('rolldown').BuildOptions} */
const rolldown_config = {
platform: 'browser',
// Mirror Netlify's edge-bundler behaviour for externalising Node.js built-ins
// see https://github.com/netlify/build/blob/main/packages/edge-bundler/node/npm_dependencies.ts#L289-L309
platform: 'node',
output: {
sourcemap: true,
codeSplitting: false
Expand All @@ -412,9 +414,19 @@ const rolldown_config = {
},
// Node built-ins are allowed, but must be prefixed with `node:`
// https://docs.netlify.com/edge-functions/api/#runtime-environment
external: builtinModules.map((id) => `node:${id}`),
resolve: {
alias: Object.fromEntries(builtinModules.map((id) => [id, `node:${id}`]))
alias: Object.fromEntries(builtinModules.map((id) => [id, `node:${id}`])),
mainFields: ['module', 'browser', 'main']
},
// Rolldown's default does not handle these files automatically
// see https://github.com/rolldown/rolldown/blob/main/crates/rolldown/src/utils/prepare_build_context.rs#L320-L336
moduleTypes: {
'.wasm': 'copy',
'.woff': 'copy',
'.woff2': 'copy',
'.ttf': 'copy',
'.eot': 'copy',
'.otf': 'copy'
}
};

Expand Down
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// imports a .wasm file directly, like resvg/satori-based packages
/**
* @param {number} a
* @param {number} b
* @returns {Promise<number>}
*/
export async function add(a, b) {
const wasm = await import('./add.wasm');
return wasm.add(a, b);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"name": "e2e-test-dep-wasm",
"version": "1.0.0",
"private": true,
"type": "module",
"exports": "./index.js"
}
10 changes: 10 additions & 0 deletions packages/adapter-netlify/test/apps/edge/build.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,13 @@ test('treeshakes component from the server bundle if SSR is turned off', () => {
const edge_function = fs.readFileSync(edge_function_path, 'utf-8');
expect(edge_function).not.toContain('this should never appear in the server bundle');
});

test('.wasm files are copied alongside the edge function', () => {
const edge_function = fs.readFileSync(edge_function_path, 'utf-8');
const wasm_import = edge_function.match(/import\(["'](\.\/[^"']+\.wasm)["']\)/)?.[1];

expect(wasm_import).toBeDefined();
expect(fs.existsSync(path.resolve(path.dirname(edge_function_path), wasm_import ?? ''))).toBe(
true
);
});
1 change: 1 addition & 0 deletions packages/adapter-netlify/test/apps/edge/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
"devDependencies": {
"@sveltejs/kit": "workspace:^",
"@sveltejs/vite-plugin-svelte": "catalog:",
"e2e-test-dep-wasm": "file:./_test_dependencies/wasm-lib",
"svelte": "catalog:",
"vite": "catalog:",
"vitest": "catalog:"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// a bare (non `node:`-prefixed) built-in import, as found in many dependencies
import { createHash } from 'crypto';

export function GET() {
return new Response(createHash('sha256').update('hello').digest('hex'));
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { add } from 'e2e-test-dep-wasm';

export async function GET() {
return new Response(String(await add(1, 2)));
}
12 changes: 12 additions & 0 deletions packages/adapter-netlify/test/apps/edge/test/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,15 @@ test('page renders on the client if SSR is turned off', async ({ page }) => {
await page.goto('/treeshake-server');
await expect(page.locator('p')).toHaveText('this should never appear in the server bundle');
});

test('bare Node built-in imports work', async ({ request }) => {
const response = await request.get('/node-builtin');
expect(await response.text()).toBe(
'2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824'
);
});

test('.wasm imports work', async ({ request }) => {
const response = await request.get('/wasm');
expect(await response.text()).toBe('3');
});
8 changes: 8 additions & 0 deletions pnpm-lock.yaml

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

Loading