Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: generate edge middleware to run reroute #12296

Open
wants to merge 52 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
6d536c4
wip
eltigerchino Jun 4, 2024
58db3ce
fix types
eltigerchino Jun 4, 2024
12c1dc5
use import alias instead of builder.copy replace
eltigerchino Jun 5, 2024
5682120
add netlify support
eltigerchino Jun 5, 2024
91aeaaf
oops we only need one edge function for serverless split
eltigerchino Jun 5, 2024
06337fd
readability
eltigerchino Jun 5, 2024
7eeb691
Merge branch 'main' into fix-reroute-split
eltigerchino Jun 6, 2024
25c38a0
cleanup vercel implementation
eltigerchino Jun 6, 2024
28e7f39
this can be sync
eltigerchino Jun 6, 2024
766d4f7
make temp file a variable
eltigerchino Jun 7, 2024
2f40af2
fix node types with @vercel/edge
eltigerchino Jun 8, 2024
6ccef50
add separate tsconfig for edge files
eltigerchino Jun 8, 2024
322ba6c
prettier
eltigerchino Jun 8, 2024
2306806
cleanup netlify
eltigerchino Jun 9, 2024
5cfc8eb
docs
eltigerchino Jun 16, 2024
d8c29f3
changeset
eltigerchino Jun 16, 2024
f28e444
Merge branch 'main' into fix-reroute-split
eltigerchino Jul 24, 2024
58dfb9d
Update .changeset/hot-guests-enjoy.md
eltigerchino Oct 10, 2024
2302812
Merge branch 'main' into fix-reroute-split
eltigerchino Oct 10, 2024
2cfc6c6
Merge branch 'main' into fix-reroute-split
eltigerchino Oct 29, 2024
1f9d964
fix broken lockfile
eltigerchino Oct 29, 2024
ab4705e
Merge branch 'main' into fix-reroute-split
eltigerchino Dec 2, 2024
2d82cac
check if reroute hook exists before generating reroute middleware
eltigerchino Dec 2, 2024
2125115
bump @vercel/edge to 1.1.2
eltigerchino Dec 2, 2024
59b5f4b
copy over reroute.js
eltigerchino Dec 2, 2024
dc440c1
how do I get esbuild to bundle vercel/edge?
eltigerchino Dec 2, 2024
1d1a67d
add rollup to bundle @vercel/edge
eltigerchino Dec 3, 2024
c19a4ae
format
eltigerchino Dec 3, 2024
1a88cfa
Merge branch 'main' into fix-reroute-split
eltigerchino Jan 17, 2025
e75d042
Merge branch 'main' into fix-reroute-split
eltigerchino Jan 21, 2025
aa125d5
disable duplicate import eslint rule for line
eltigerchino Jan 21, 2025
014e5dd
bump @vercel/edge
eltigerchino Jan 21, 2025
11c4a70
strip sveltekit url internals before passing url to reroute
eltigerchino Jan 21, 2025
e9a2f85
revert
eltigerchino Jan 21, 2025
a589063
Update .changeset/hot-guests-enjoy.md
eltigerchino Jan 21, 2025
46ac4df
Update documentation/docs/25-build-and-deploy/90-adapter-vercel.md
eltigerchino Jan 21, 2025
f965bc0
Merge branch 'main' into fix-reroute-split
eltigerchino Jan 21, 2025
bb7418f
restore original path and export middleware reroute function
eltigerchino Jan 23, 2025
33c763f
Merge branch 'main' into fix-reroute-split
eltigerchino Jan 23, 2025
1da5a79
remove logs
eltigerchino Jan 23, 2025
d13fb42
bump adapter kit peer version
eltigerchino Jan 23, 2025
25a88d0
format
eltigerchino Jan 23, 2025
435e12e
reword changeset
eltigerchino Jan 23, 2025
8d667e6
fix incorrect merge
eltigerchino Jan 23, 2025
95d0d42
format
eltigerchino Jan 23, 2025
4fb32a5
apparently the edge middleware preserves the original url so we don't…
eltigerchino Jan 23, 2025
9934caa
format
eltigerchino Jan 23, 2025
705f2d1
fix merge discrepencies
eltigerchino Jan 23, 2025
a352d7c
Merge branch 'main' into fix-reroute-split
eltigerchino Jan 24, 2025
e38a660
fix endless loop on Netlify
eltigerchino Jan 24, 2025
5783e9b
restore original path
eltigerchino Jan 24, 2025
09a744b
format
eltigerchino Jan 24, 2025
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
6 changes: 6 additions & 0 deletions .changeset/hot-guests-enjoy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@sveltejs/adapter-netlify": minor
"@sveltejs/adapter-vercel": minor
---

fix: run `reroute` in an edge middleware if the app has been split into multiple functions
6 changes: 6 additions & 0 deletions documentation/docs/25-build-and-deploy/80-adapter-netlify.md
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,12 @@ Additionally, you can add your own Netlify functions by creating a directory for
directory = "functions"
```

## Notes

### Individual functions and `reroute`

If the `split` option is set to `true` in the adapter config, the [`reroute`](/docs/hooks#universal-hooks-reroute) function will be deployed as an edge middleware that runs before any individual function.

## Troubleshooting

### Accessing the file system
Expand Down
4 changes: 4 additions & 0 deletions documentation/docs/25-build-and-deploy/90-adapter-vercel.md
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,10 @@ If you have Vercel functions contained in the `api` directory at the project's r

Projects created before a certain date may default to using an older Node version than what SvelteKit currently requires. You can [change the Node version in your project settings](https://vercel.com/docs/concepts/functions/serverless-functions/runtimes/node-js#node.js-version).

### Individual functions and `reroute`

If the `split` option is set to `true` for a route, or at the adapter level, the [`reroute`](/docs/hooks#universal-hooks-reroute) function will be deployed as an edge middleware that runs before any individual function.

## Troubleshooting

### Accessing the file system
Expand Down
93 changes: 68 additions & 25 deletions packages/adapter-netlify/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,13 @@ export default function ({ split = false, edge = edge_set_in_env_var } = {}) {
await generate_edge_functions({ builder });
} else {
generate_lambda_functions({ builder, split, publish });

/** @type {string | void} */
let reroute_path;

if (split && (reroute_path = await builder.getReroutePath())) {
await generate_reroute_middleware({ builder, reroute_path });
}
}
},

Expand All @@ -115,6 +122,7 @@ export default function ({ split = false, edge = edge_set_in_env_var } = {}) {
}
};
}

/**
* @param { object } params
* @param {import('@sveltejs/kit').Builder} params.builder
Expand All @@ -127,6 +135,7 @@ async function generate_edge_functions({ builder }) {
builder.mkdirp('.netlify/edge-functions');

builder.log.minor('Generating Edge Function...');

const relativePath = posix.relative(tmp, builder.getServerDirectory());

builder.copy(`${files}/edge.js`, `${tmp}/entry.js`, {
Expand All @@ -136,12 +145,67 @@ async function generate_edge_functions({ builder }) {
}
});

const manifest = builder.generateManifest({
relativePath
await bundle_edge_function({ builder, name: 'render' });
}

/**
* @param {object} params
* @param {import('@sveltejs/kit').Builder} params.builder
* @param {string} params.reroute_path
*/
async function generate_reroute_middleware({ builder, reroute_path }) {
const tmp = builder.getBuildDirectory('netlify-tmp');
builder.rimraf(tmp);
builder.mkdirp(tmp);

builder.mkdirp('.netlify/edge-functions');

builder.log.minor('Generating Reroute Edge Function...');

builder.copy(`${files}/reroute.js`, `${tmp}/entry.js`, {
replace: {
__HOOKS__: reroute_path
}
});

await bundle_edge_function({ builder, name: 'reroute' });
}

/**
*
* @param {object} params
* @param {import('@sveltejs/kit').Builder} params.builder
* @param {string} params.name
*/
async function bundle_edge_function({ builder, name }) {
const tmp = builder.getBuildDirectory('netlify-tmp');

const relativePath = posix.relative(tmp, builder.getServerDirectory());
const manifest = builder.generateManifest({ relativePath });
writeFileSync(`${tmp}/manifest.js`, `export const manifest = ${manifest};\n`);

await esbuild.build({
entryPoints: [`${tmp}/entry.js`],
outfile: `.netlify/edge-functions/${name}.js`,
bundle: true,
format: 'esm',
platform: 'browser',
sourcemap: 'linked',
target: 'es2020',
loader: {
'.wasm': 'copy',
'.woff': 'copy',
'.woff2': 'copy',
'.ttf': 'copy',
'.eot': 'copy',
'.otf': 'copy'
},
// 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}`),
alias: Object.fromEntries(builtinModules.map((id) => [id, `node:${id}`]))
});

/** @type {{ assets: Set<string> }} */
const { assets } = (await import(`${tmp}/manifest.js`)).manifest;

Expand Down Expand Up @@ -170,38 +234,17 @@ async function generate_edge_functions({ builder }) {
const edge_manifest = {
functions: [
{
function: 'render',
function: name,
path,
excludedPath
}
],
version: 1
};

await esbuild.build({
entryPoints: [`${tmp}/entry.js`],
outfile: '.netlify/edge-functions/render.js',
bundle: true,
format: 'esm',
platform: 'browser',
sourcemap: 'linked',
target: 'es2020',
loader: {
'.wasm': 'copy',
'.woff': 'copy',
'.woff2': 'copy',
'.ttf': 'copy',
'.eot': 'copy',
'.otf': 'copy'
},
// 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}`),
alias: Object.fromEntries(builtinModules.map((id) => [id, `node:${id}`]))
});

writeFileSync('.netlify/edge-functions/manifest.json', JSON.stringify(edge_manifest));
}

/**
* @param { object } params
* @param {import('@sveltejs/kit').Builder} params.builder
Expand Down
7 changes: 7 additions & 0 deletions packages/adapter-netlify/internal.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,10 @@ declare module 'MANIFEST' {

export const manifest: SSRManifest;
}

declare module '__HOOKS__' {
// eslint-disable-next-line no-duplicate-imports
import { Reroute } from '@sveltejs/kit';

export const reroute: Reroute;
}
2 changes: 1 addition & 1 deletion packages/adapter-netlify/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,6 @@
"vitest": "^3.0.1"
},
"peerDependencies": {
"@sveltejs/kit": "^2.4.0"
"@sveltejs/kit": "^2.17.0"
}
}
40 changes: 26 additions & 14 deletions packages/adapter-netlify/rollup.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,32 @@ import { nodeResolve } from '@rollup/plugin-node-resolve';
import commonjs from '@rollup/plugin-commonjs';
import json from '@rollup/plugin-json';

/** @type {import('rollup').RollupOptions} */
const config = {
input: {
serverless: 'src/serverless.js',
shims: 'src/shims.js'
/** @type {import('rollup').RollupOptions[]} */
const config = [
{
input: {
serverless: 'src/serverless.js',
shims: 'src/shims.js'
},
output: {
dir: 'files/esm',
format: 'esm'
},
// @ts-ignore https://github.com/rollup/plugins/issues/1329
plugins: [nodeResolve({ preferBuiltins: true }), commonjs(), json()],
external: (id) => id === '0SERVER' || id.startsWith('node:'),
preserveEntrySignatures: 'exports-only'
},
output: {
dir: 'files/esm',
format: 'esm'
},
// @ts-ignore https://github.com/rollup/plugins/issues/1329
plugins: [nodeResolve({ preferBuiltins: true }), commonjs(), json()],
external: (id) => id === '0SERVER' || id.startsWith('node:'),
preserveEntrySignatures: 'exports-only'
};
{
input: 'src/reroute.js',
output: {
file: 'files/reroute.js',
format: 'esm'
},
plugins: [nodeResolve({ preferBuiltins: true })],
external: (id) => id === '__HOOKS__',
preserveEntrySignatures: 'exports-only'
}
];

export default config;
18 changes: 18 additions & 0 deletions packages/adapter-netlify/src/reroute.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { reroute } from '__HOOKS__';
import { applyReroute } from '@sveltejs/kit/adapter';

/**
* @param {Request} request
* @returns {URL | undefined}
*/
export default function middleware(request) {
const url = new URL(request.url);
const rerouted_path = applyReroute(url, reroute);

// a rewrite on Netlify will cause this function to run again with the new URL
// instead of moving onto the route function, so we only return a URL if
// the reroute path is different from the original to avoid an endless loop
if (rerouted_path && url.pathname !== rerouted_path.pathname) {
return rerouted_path;
}
}
1 change: 1 addition & 0 deletions packages/adapter-vercel/.gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
.DS_Store
node_modules
/files
Loading
Loading