From 793a32ada6fed6eb98902bc8800bef92d2a8f858 Mon Sep 17 00:00:00 2001 From: Justin Ridgewell Date: Thu, 23 Feb 2023 00:06:37 -0500 Subject: [PATCH 1/3] Extract middleware matcher config In order to setup the middleware in routing, we need to know what routes to match on without executing the middleware edgeInfo itself. --- crates/next-core/js/src/entry/router.ts | 6 ++- crates/next-core/src/router.rs | 55 ++++++++++++++++++------- crates/next-core/src/util.rs | 47 ++++++++++++++++++++- 3 files changed, 91 insertions(+), 17 deletions(-) diff --git a/crates/next-core/js/src/entry/router.ts b/crates/next-core/js/src/entry/router.ts index a5fec22528e212..3ce0fd6cf83e6c 100644 --- a/crates/next-core/js/src/entry/router.ts +++ b/crates/next-core/js/src/entry/router.ts @@ -11,6 +11,7 @@ import { PHASE_DEVELOPMENT_SERVER } from "next/dist/shared/lib/constants"; import "next/dist/server/node-polyfill-fetch.js"; import middlewareChunkGroup from "MIDDLEWARE_CHUNK_GROUP"; +import middlewareConfig from "MIDDLEWARE_CONFIG"; type RouterRequest = { method: string; @@ -83,7 +84,10 @@ async function getResolveRoute( env: [], assets: [], }; - return await makeResolver(dir, nextConfig, edgeInfo); + return await makeResolver(dir, nextConfig, { + edgeInfo, + config: middlewareConfig, + }); } export default async function route( diff --git a/crates/next-core/src/router.rs b/crates/next-core/src/router.rs index 64ad9f628a1942..cfab51181231ff 100644 --- a/crates/next-core/src/router.rs +++ b/crates/next-core/src/router.rs @@ -2,6 +2,7 @@ use std::collections::HashMap; use anyhow::{bail, Result}; use serde::Deserialize; +use serde_json::json; use turbo_tasks::{ primitives::{JsonValueVc, StringsVc}, CompletionVc, Value, @@ -40,6 +41,7 @@ use crate::{ }, next_import_map::get_next_build_import_map, next_server::context::ServerContextType, + util::{parse_config_from_source, NextSourceConfigVc}, }; #[turbo_tasks::function] @@ -194,26 +196,49 @@ async fn config_assets( // is no middleware file, then we need to generate a default empty manifest // and we cannot process it with the next-edge transition because it // requires a real file for some reason. - let middleware_manifest = match &*middleware_config { - Some(c) => context.with_transition("next-edge").process( - c.as_asset(), - Value::new(ReferenceType::EcmaScriptModules( - EcmaScriptModulesReferenceSubType::Undefined, - )), - ), - None => as_es_module_asset( - VirtualAssetVc::new( - project_path.join("middleware.js"), - File::from("export default [];").into(), + let (manifest, config) = match &*middleware_config { + Some(c) => { + let manifest = context.with_transition("next-edge").process( + c.as_asset(), + Value::new(ReferenceType::EcmaScriptModules( + EcmaScriptModulesReferenceSubType::Undefined, + )), + ); + let config = parse_config_from_source(c.as_asset()); + (manifest, config) + } + None => { + let manifest = as_es_module_asset( + VirtualAssetVc::new( + project_path.join("middleware.js"), + File::from("export default [];").into(), + ) + .as_asset(), + context, ) - .as_asset(), - context, + .as_asset(); + let config = NextSourceConfigVc::default(); + (manifest, config) + } + }; + + let config_asset = as_es_module_asset( + VirtualAssetVc::new( + project_path.join("middleware_config.js"), + File::from(format!( + "export default {};", + json!({ "matcher": &*config.await?.matcher }) + )) + .into(), ) .as_asset(), - }; + context, + ) + .as_asset(); let mut inner = HashMap::new(); - inner.insert("MIDDLEWARE_CHUNK_GROUP".to_string(), middleware_manifest); + inner.insert("MIDDLEWARE_CHUNK_GROUP".to_string(), manifest); + inner.insert("MIDDLEWARE_CONFIG".to_string(), config_asset); Ok(InnerAssetsVc::cell(inner)) } diff --git a/crates/next-core/src/util.rs b/crates/next-core/src/util.rs index fb37acc83dd510..1a60ba4f8a310c 100644 --- a/crates/next-core/src/util.rs +++ b/crates/next-core/src/util.rs @@ -89,6 +89,17 @@ pub enum NextRuntime { #[derive(Default)] pub struct NextSourceConfig { pub runtime: NextRuntime, + + /// Middleware router matchers + pub matcher: Option>, +} + +#[turbo_tasks::value_impl] +impl NextSourceConfigVc { + #[turbo_tasks::function] + pub fn default() -> Self { + NextSourceConfig::default().cell() + } } /// An issue that occurred while resolving the React Refresh runtime module. @@ -179,7 +190,7 @@ pub async fn parse_config_from_source(module_asset: AssetVc) -> Result NextSourceConfig { @@ -229,6 +240,40 @@ fn parse_config_from_js_value(module_asset: AssetVc, value: &JsValue) -> NextSou ); } } + if key == "matcher" { + let mut matchers = vec![]; + match value { + JsValue::Constant(matcher) => { + if let Some(matcher) = matcher.as_str() { + matchers.push(matcher.to_string()); + } else { + invalid_config( + "The matcher property must be a string or array of \ + strings", + value, + ); + } + } + JsValue::Array { items, .. } => { + for item in items { + if let Some(matcher) = item.as_str() { + matchers.push(matcher.to_string()); + } else { + invalid_config( + "The matcher property must be a string or array \ + of strings", + value, + ); + } + } + } + _ => invalid_config( + "The matcher property must be a string or array of strings", + value, + ), + } + config.matcher = Some(matchers); + } } else { invalid_config( "The exported config object must not contain non-constant strings.", From 7052d4e930c00fba15fc583ae9a70c698b93d7aa Mon Sep 17 00:00:00 2001 From: Justin Ridgewell Date: Thu, 23 Feb 2023 11:45:17 -0500 Subject: [PATCH 2/3] Fix deref --- crates/next-core/src/router.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/next-core/src/router.rs b/crates/next-core/src/router.rs index cfab51181231ff..23bf1f2182d023 100644 --- a/crates/next-core/src/router.rs +++ b/crates/next-core/src/router.rs @@ -227,7 +227,7 @@ async fn config_assets( project_path.join("middleware_config.js"), File::from(format!( "export default {};", - json!({ "matcher": &*config.await?.matcher }) + json!({ "matcher": &config.await?.matcher }) )) .into(), ) From 24e02cc5c49df97739d575712fefa368d5f4e11d Mon Sep 17 00:00:00 2001 From: Justin Ridgewell Date: Fri, 24 Feb 2023 21:09:00 -0500 Subject: [PATCH 3/3] Update middleware information --- crates/next-core/js/src/entry/edge-bootstrap.ts | 3 ++- crates/next-core/js/src/entry/router.ts | 16 +++------------- crates/next-core/src/app_source.rs | 1 + crates/next-core/src/next_edge/transition.rs | 11 +++++++++-- crates/next-core/src/page_source.rs | 1 + crates/next-core/src/router.rs | 3 ++- 6 files changed, 18 insertions(+), 17 deletions(-) diff --git a/crates/next-core/js/src/entry/edge-bootstrap.ts b/crates/next-core/js/src/entry/edge-bootstrap.ts index 6acd3668934fb1..0ad3d2c9baf816 100644 --- a/crates/next-core/js/src/entry/edge-bootstrap.ts +++ b/crates/next-core/js/src/entry/edge-bootstrap.ts @@ -1,3 +1,4 @@ +declare const NAME: string; declare const PAGE: string; import { adapter, enhanceGlobals } from "next/dist/server/web/adapter"; @@ -15,7 +16,7 @@ if (typeof handler !== "function") { // @ts-ignore globalThis._ENTRIES = { - middleware_edge: { + [`middleware_${NAME}`]: { default: function (opts: any) { return adapter({ ...opts, diff --git a/crates/next-core/js/src/entry/router.ts b/crates/next-core/js/src/entry/router.ts index 3ce0fd6cf83e6c..c55c9c9803db9d 100644 --- a/crates/next-core/js/src/entry/router.ts +++ b/crates/next-core/js/src/entry/router.ts @@ -1,10 +1,9 @@ import type { Ipc } from "@vercel/turbopack-next/ipc/index"; import type { IncomingMessage, ServerResponse } from "node:http"; import { Buffer } from "node:buffer"; -import { join } from "node:path"; import { createServer, makeRequest } from "@vercel/turbopack-next/ipc/server"; import { toPairs } from "@vercel/turbopack-next/internal/headers"; -import { makeResolver } from "next/dist/server/router.js"; +import { makeResolver } from "next/dist/server/lib/route-resolver"; import loadConfig from "next/dist/server/config"; import { PHASE_DEVELOPMENT_SERVER } from "next/dist/shared/lib/constants"; @@ -75,18 +74,9 @@ async function getResolveRoute( true ); - const edgeInfo = { - name: "edge", - paths: middlewareChunkGroup.map((chunk: string) => - join(process.cwd(), chunk) - ), - wasm: [], - env: [], - assets: [], - }; return await makeResolver(dir, nextConfig, { - edgeInfo, - config: middlewareConfig, + files: middlewareChunkGroup, + matcher: middlewareConfig.matcher, }); } diff --git a/crates/next-core/src/app_source.rs b/crates/next-core/src/app_source.rs index 76c4839a09a6bf..29c4890d1abc62 100644 --- a/crates/next-core/src/app_source.rs +++ b/crates/next-core/src/app_source.rs @@ -202,6 +202,7 @@ fn next_route_transition( output_path, base_path: app_dir, bootstrap_file: next_js_file("entry/app/route-bootstrap.ts"), + entry_name: "edge".to_string(), } .cell() .into() diff --git a/crates/next-core/src/next_edge/transition.rs b/crates/next-core/src/next_edge/transition.rs index e8fe9841f8b5a6..242e91e7c3e8a3 100644 --- a/crates/next-core/src/next_edge/transition.rs +++ b/crates/next-core/src/next_edge/transition.rs @@ -29,6 +29,7 @@ pub struct NextEdgeTransition { pub output_path: FileSystemPathVc, pub base_path: FileSystemPathVc, pub bootstrap_file: FileContentVc, + pub entry_name: String, } #[turbo_tasks::value_impl] @@ -81,8 +82,14 @@ impl Transition for NextEdgeTransition { } else { path }; - let mut new_content = - RopeBuilder::from(format!("const PAGE = {};\n", stringify_js(path)).into_bytes()); + let mut new_content = RopeBuilder::from( + format!( + "const NAME={};\nconst PAGE = {};\n", + stringify_js(&self.entry_name), + stringify_js(path) + ) + .into_bytes(), + ); new_content.concat(base.content()); let file = File::from(new_content.build()); let virtual_asset = VirtualAssetVc::new( diff --git a/crates/next-core/src/page_source.rs b/crates/next-core/src/page_source.rs index ef646eedff5783..52974f1bce203f 100644 --- a/crates/next-core/src/page_source.rs +++ b/crates/next-core/src/page_source.rs @@ -155,6 +155,7 @@ pub async fn create_page_source( output_path, base_path: project_path, bootstrap_file: next_js_file("entry/edge-bootstrap.ts"), + entry_name: "edge".to_string(), } .cell() .into(); diff --git a/crates/next-core/src/router.rs b/crates/next-core/src/router.rs index 23bf1f2182d023..cdb49e6e09b22c 100644 --- a/crates/next-core/src/router.rs +++ b/crates/next-core/src/router.rs @@ -287,9 +287,10 @@ fn edge_transition_map( edge_compile_time_info, edge_chunking_context, edge_resolve_options_context, - output_path, + output_path: output_path.root(), base_path: project_path, bootstrap_file: next_js_file("entry/edge-bootstrap.ts"), + entry_name: "middleware".to_string(), } .cell() .into();