Skip to content

Commit f9d12d1

Browse files
fix(turbopack): middleware path and aliases (#56804)
### Description - Adds the page path to the middleware template (and also uses the template from the next.js loader) - ESM aliases for the edge context - Fix for the process polyfill to make it possible to import from `dist/esm` - Fix for the `server-only`/`client-only` aliases Closes WEB-1779
1 parent fe0bfbf commit f9d12d1

File tree

6 files changed

+113
-40
lines changed

6 files changed

+113
-40
lines changed

packages/next-swc/crates/next-core/src/middleware.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ pub async fn get_middleware_module(
3636
project_root,
3737
indexmap! {
3838
"VAR_USERLAND" => INNER.to_string(),
39+
"VAR_DEFINITION_PAGE" => "/middleware".to_string(),
3940
},
4041
indexmap! {},
4142
)

packages/next-swc/crates/next-core/src/next_import_map.rs

Lines changed: 91 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -365,6 +365,52 @@ pub async fn get_next_edge_import_map(
365365
) -> Result<Vc<ImportMap>> {
366366
let mut import_map = ImportMap::empty();
367367

368+
// https://github.com/vercel/next.js/blob/786ef25e529e1fb2dda398aebd02ccbc8d0fb673/packages/next/src/build/webpack-config.ts#L815-L861
369+
370+
// Alias next/dist imports to next/dist/esm assets
371+
insert_wildcard_alias_map(
372+
&mut import_map,
373+
project_path,
374+
indexmap! {
375+
"next/dist/build/" => "next/dist/esm/build/*".to_string(),
376+
"next/dist/client/" => "next/dist/esm/client/*".to_string(),
377+
"next/dist/shared/" => "next/dist/esm/shared/*".to_string(),
378+
"next/dist/pages/" => "next/dist/esm/pages/*".to_string(),
379+
"next/dist/lib/" => "next/dist/esm/lib/*".to_string(),
380+
"next/dist/server/" => "next/dist/esm/server/*".to_string(),
381+
},
382+
);
383+
384+
// Alias the usage of next public APIs
385+
insert_exact_alias_map(
386+
&mut import_map,
387+
project_path,
388+
indexmap! {
389+
"next/app" => "next/dist/esm/pages/_app".to_string(),
390+
"next/document" => "next/dist/esm/pages/_document".to_string(),
391+
"next/dynamic" => "next/dist/esm/shared/lib/dynamic".to_string(),
392+
"next/head" => "next/dist/esm/shared/lib/head".to_string(),
393+
"next/headers" => "next/dist/esm/client/components/headers".to_string(),
394+
"next/image" => "next/dist/esm/shared/lib/image-external".to_string(),
395+
"next/link" => "next/dist/esm/client/link".to_string(),
396+
"next/navigation" => "next/dist/esm/client/components/navigation".to_string(),
397+
"next/router" => "next/dist/esm/client/router".to_string(),
398+
"next/script" => "next/dist/esm/client/script".to_string(),
399+
"next/server" => "next/dist/esm/server/web/exports/index".to_string(),
400+
401+
"next/dist/client/components/headers" => "next/dist/esm/client/components/headers".to_string(),
402+
"next/dist/client/components/navigation" => "next/dist/esm/client/components/navigation".to_string(),
403+
"next/dist/client/link" => "next/dist/esm/client/link".to_string(),
404+
"next/dist/client/router" => "next/dist/esm/client/router".to_string(),
405+
"next/dist/client/script" => "next/dist/esm/client/script".to_string(),
406+
"next/dist/pages/_app" => "next/dist/esm/pages/_app".to_string(),
407+
"next/dist/pages/_document" => "next/dist/esm/pages/_document".to_string(),
408+
"next/dist/shared/lib/dynamic" => "next/dist/esm/shared/lib/dynamic".to_string(),
409+
"next/dist/shared/lib/head" => "next/dist/esm/shared/lib/head".to_string(),
410+
"next/dist/shared/lib/image-external" => "next/dist/esm/shared/lib/image-external".to_string(),
411+
},
412+
);
413+
368414
insert_next_shared_aliases(
369415
&mut import_map,
370416
project_path,
@@ -828,17 +874,41 @@ async fn insert_next_server_special_aliases(
828874
}
829875

830876
// see https://github.com/vercel/next.js/blob/8013ef7372fc545d49dbd060461224ceb563b454/packages/next/src/build/webpack-config.ts#L1449-L1531
831-
insert_exact_alias_map(
832-
import_map,
833-
project_path,
834-
indexmap! {
835-
"server-only" => "next/dist/compiled/server-only/empty".to_string(),
836-
"client-only" => "next/dist/compiled/client-only/index".to_string(),
837-
"next/dist/compiled/server-only" => "next/dist/compiled/server-only/empty".to_string(),
838-
"next/dist/compiled/client-only" => "next/dist/compiled/client-only/index".to_string(),
839-
},
840-
);
877+
match ty {
878+
ServerContextType::Pages { .. }
879+
| ServerContextType::PagesData { .. }
880+
| ServerContextType::AppSSR { .. } => {
881+
insert_exact_alias_map(
882+
import_map,
883+
project_path,
884+
indexmap! {
885+
"server-only" => "next/dist/compiled/server-only/index".to_string(),
886+
"client-only" => "next/dist/compiled/client-only/index".to_string(),
887+
"next/dist/compiled/server-only" => "next/dist/compiled/server-only/index".to_string(),
888+
"next/dist/compiled/client-only" => "next/dist/compiled/client-only/index".to_string(),
889+
},
890+
);
891+
}
892+
// TODO: should include `ServerContextType::PagesApi` routes, but that type doesn't exist.
893+
ServerContextType::AppRSC { .. }
894+
| ServerContextType::AppRoute { .. }
895+
| ServerContextType::Middleware => {
896+
insert_exact_alias_map(
897+
import_map,
898+
project_path,
899+
indexmap! {
900+
"server-only" => "next/dist/compiled/server-only/empty".to_string(),
901+
"client-only" => "next/dist/compiled/client-only/error".to_string(),
902+
"next/dist/compiled/server-only" => "next/dist/compiled/server-only/empty".to_string(),
903+
"next/dist/compiled/client-only" => "next/dist/compiled/client-only/error".to_string(),
904+
},
905+
);
906+
}
907+
}
841908

909+
// Potential the bundle introduced into middleware and api can be poisoned by
910+
// client-only but not being used, so we disabled the `client-only` erroring
911+
// on these layers. `server-only` is still available.
842912
if ty == ServerContextType::Middleware {
843913
insert_exact_alias_map(
844914
import_map,
@@ -1054,6 +1124,17 @@ fn insert_exact_alias_map(
10541124
}
10551125
}
10561126

1127+
fn insert_wildcard_alias_map(
1128+
import_map: &mut ImportMap,
1129+
project_path: Vc<FileSystemPath>,
1130+
map: IndexMap<&'static str, String>,
1131+
) {
1132+
for (pattern, request) in map {
1133+
import_map
1134+
.insert_wildcard_alias(pattern, request_to_import_mapping(project_path, &request));
1135+
}
1136+
}
1137+
10571138
/// Inserts an alias to an alternative of import mappings into an import map.
10581139
fn insert_alias_to_alternatives<'a>(
10591140
import_map: &mut ImportMap,

packages/next/src/build/load-entrypoint.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,12 @@ const TEMPLATES_ESM_FOLDER = path.normalize(
2626

2727
export async function loadEntrypoint(
2828
entrypoint:
29-
| 'pages'
30-
| 'pages-api'
3129
| 'app-page'
3230
| 'app-route'
33-
| 'edge-app-route',
31+
| 'edge-app-route'
32+
| 'middleware'
33+
| 'pages'
34+
| 'pages-api',
3435
replacements: Record<`VAR_${string}`, string>,
3536
injections?: Record<string, string>
3637
): Promise<string> {
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
module.exports =
22
global.process?.env && typeof global.process?.env === 'object'
33
? global.process
4-
: require('../../compiled/process')
4+
: require('next/dist/compiled/process')

packages/next/src/build/templates/middleware.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,18 +10,20 @@ import * as _mod from 'VAR_USERLAND'
1010
const mod = { ..._mod }
1111
const handler = mod.middleware || mod.default
1212

13+
const page = 'VAR_DEFINITION_PAGE'
14+
1315
if (typeof handler !== 'function') {
1416
throw new Error(
15-
`The Middleware must export a \`middleware\` or a \`default\` function`
17+
`The Middleware "${page}" must export a \`middleware\` or a \`default\` function`
1618
)
1719
}
1820

19-
export default function (
21+
export default function nHandler(
2022
opts: Omit<AdapterOptions, 'IncrementalCache' | 'page' | 'handler'>
2123
) {
2224
return adapter({
2325
...opts,
24-
page: '',
26+
page,
2527
handler,
2628
})
2729
}

packages/next/src/build/webpack/loaders/next-middleware-loader.ts

Lines changed: 11 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ import type {
33
MiddlewareMatcher,
44
} from '../../analysis/get-page-static-info'
55
import { getModuleBuildInfo } from './get-module-build-info'
6-
import { stringifyRequest } from '../stringify-request'
76
import { MIDDLEWARE_LOCATION_REGEXP } from '../../../lib/constants'
7+
import { loadEntrypoint } from '../../load-entrypoint'
88

99
export type MiddlewareLoaderOptions = {
1010
absolutePagePath: string
@@ -27,7 +27,7 @@ export function decodeMatchers(encodedMatchers: string) {
2727
) as MiddlewareMatcher[]
2828
}
2929

30-
export default function middlewareLoader(this: any) {
30+
export default async function middlewareLoader(this: any) {
3131
const {
3232
absolutePagePath,
3333
page,
@@ -37,7 +37,11 @@ export default function middlewareLoader(this: any) {
3737
middlewareConfig: middlewareConfigBase64,
3838
}: MiddlewareLoaderOptions = this.getOptions()
3939
const matchers = encodedMatchers ? decodeMatchers(encodedMatchers) : undefined
40-
const stringifiedPagePath = stringifyRequest(this, absolutePagePath)
40+
const pagePath = this.utils.contextify(
41+
this.context || this.rootContext,
42+
absolutePagePath
43+
)
44+
4145
const middlewareConfig: MiddlewareConfig = JSON.parse(
4246
Buffer.from(middlewareConfigBase64, 'base64').toString()
4347
)
@@ -55,24 +59,8 @@ export default function middlewareLoader(this: any) {
5559
middlewareConfig,
5660
}
5761

58-
return `
59-
import 'next/dist/esm/server/web/globals'
60-
import { adapter } from 'next/dist/esm/server/web/adapter'
61-
import * as _mod from ${stringifiedPagePath}
62-
63-
const mod = { ..._mod }
64-
const handler = mod.middleware || mod.default
65-
66-
if (typeof handler !== 'function') {
67-
throw new Error('The Middleware "pages${page}" must export a \`middleware\` or a \`default\` function');
68-
}
69-
70-
export default function nHandler(opts) {
71-
return adapter({
72-
...opts,
73-
page: ${JSON.stringify(page)},
74-
handler,
75-
})
76-
}
77-
`
62+
return await loadEntrypoint('middleware', {
63+
VAR_USERLAND: pagePath,
64+
VAR_DEFINITION_PAGE: page,
65+
})
7866
}

0 commit comments

Comments
 (0)