Turbopack: Experimental dev app pages support (#52680)
This implements app pages and routes for the Nexturbo API. ## Turbopack updates * https://github.com/vercel/turbo/pull/5527 <!-- Alex Kirszenberg - AdjacencyMap::reverse_topological (+ fixes) -->
This commit is contained in:
parent
e5b35894a7
commit
dd56a77e91
34 changed files with 1634 additions and 868 deletions
75
Cargo.lock
generated
75
Cargo.lock
generated
|
@ -412,7 +412,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "auto-hash-map"
|
name = "auto-hash-map"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230716.2#8433a321545de30374b5374320625b92c663f5dc"
|
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230717.2#b0695455647275362c780c85f7e0bcbb3d8d64ec"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
@ -3377,6 +3377,7 @@ dependencies = [
|
||||||
"next-core",
|
"next-core",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"serde",
|
"serde",
|
||||||
|
"serde_json",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tracing",
|
"tracing",
|
||||||
"tracing-subscriber",
|
"tracing-subscriber",
|
||||||
|
@ -3416,12 +3417,14 @@ dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"async-recursion",
|
"async-recursion",
|
||||||
"async-trait",
|
"async-trait",
|
||||||
|
"base64 0.21.0",
|
||||||
"const_format",
|
"const_format",
|
||||||
"futures",
|
"futures",
|
||||||
"indexmap",
|
"indexmap",
|
||||||
"indoc",
|
"indoc",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"mime",
|
"mime",
|
||||||
|
"mime_guess",
|
||||||
"next-transform-dynamic",
|
"next-transform-dynamic",
|
||||||
"next-transform-font",
|
"next-transform-font",
|
||||||
"next-transform-strip-page-exports",
|
"next-transform-strip-page-exports",
|
||||||
|
@ -3599,7 +3602,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "node-file-trace"
|
name = "node-file-trace"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230716.2#8433a321545de30374b5374320625b92c663f5dc"
|
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230717.2#b0695455647275362c780c85f7e0bcbb3d8d64ec"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"serde",
|
"serde",
|
||||||
|
@ -7259,7 +7262,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "turbo-tasks"
|
name = "turbo-tasks"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230716.2#8433a321545de30374b5374320625b92c663f5dc"
|
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230717.2#b0695455647275362c780c85f7e0bcbb3d8d64ec"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"async-trait",
|
"async-trait",
|
||||||
|
@ -7291,7 +7294,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "turbo-tasks-build"
|
name = "turbo-tasks-build"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230716.2#8433a321545de30374b5374320625b92c663f5dc"
|
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230717.2#b0695455647275362c780c85f7e0bcbb3d8d64ec"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"cargo-lock",
|
"cargo-lock",
|
||||||
|
@ -7303,7 +7306,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "turbo-tasks-bytes"
|
name = "turbo-tasks-bytes"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230716.2#8433a321545de30374b5374320625b92c663f5dc"
|
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230717.2#b0695455647275362c780c85f7e0bcbb3d8d64ec"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"bytes",
|
"bytes",
|
||||||
|
@ -7318,7 +7321,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "turbo-tasks-env"
|
name = "turbo-tasks-env"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230716.2#8433a321545de30374b5374320625b92c663f5dc"
|
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230717.2#b0695455647275362c780c85f7e0bcbb3d8d64ec"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"dotenvs",
|
"dotenvs",
|
||||||
|
@ -7332,7 +7335,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "turbo-tasks-fetch"
|
name = "turbo-tasks-fetch"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230716.2#8433a321545de30374b5374320625b92c663f5dc"
|
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230717.2#b0695455647275362c780c85f7e0bcbb3d8d64ec"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"indexmap",
|
"indexmap",
|
||||||
|
@ -7349,7 +7352,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "turbo-tasks-fs"
|
name = "turbo-tasks-fs"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230716.2#8433a321545de30374b5374320625b92c663f5dc"
|
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230717.2#b0695455647275362c780c85f7e0bcbb3d8d64ec"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"auto-hash-map",
|
"auto-hash-map",
|
||||||
|
@ -7379,7 +7382,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "turbo-tasks-hash"
|
name = "turbo-tasks-hash"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230716.2#8433a321545de30374b5374320625b92c663f5dc"
|
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230717.2#b0695455647275362c780c85f7e0bcbb3d8d64ec"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base16",
|
"base16",
|
||||||
"hex",
|
"hex",
|
||||||
|
@ -7391,7 +7394,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "turbo-tasks-macros"
|
name = "turbo-tasks-macros"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230716.2#8433a321545de30374b5374320625b92c663f5dc"
|
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230717.2#b0695455647275362c780c85f7e0bcbb3d8d64ec"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"convert_case 0.6.0",
|
"convert_case 0.6.0",
|
||||||
|
@ -7405,7 +7408,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "turbo-tasks-macros-shared"
|
name = "turbo-tasks-macros-shared"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230716.2#8433a321545de30374b5374320625b92c663f5dc"
|
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230717.2#b0695455647275362c780c85f7e0bcbb3d8d64ec"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
@ -7415,7 +7418,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "turbo-tasks-malloc"
|
name = "turbo-tasks-malloc"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230716.2#8433a321545de30374b5374320625b92c663f5dc"
|
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230717.2#b0695455647275362c780c85f7e0bcbb3d8d64ec"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"mimalloc",
|
"mimalloc",
|
||||||
]
|
]
|
||||||
|
@ -7423,7 +7426,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "turbo-tasks-memory"
|
name = "turbo-tasks-memory"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230716.2#8433a321545de30374b5374320625b92c663f5dc"
|
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230717.2#b0695455647275362c780c85f7e0bcbb3d8d64ec"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"auto-hash-map",
|
"auto-hash-map",
|
||||||
|
@ -7446,7 +7449,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "turbo-tasks-testing"
|
name = "turbo-tasks-testing"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230716.2#8433a321545de30374b5374320625b92c663f5dc"
|
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230717.2#b0695455647275362c780c85f7e0bcbb3d8d64ec"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"auto-hash-map",
|
"auto-hash-map",
|
||||||
|
@ -7459,7 +7462,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "turbopack"
|
name = "turbopack"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230716.2#8433a321545de30374b5374320625b92c663f5dc"
|
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230717.2#b0695455647275362c780c85f7e0bcbb3d8d64ec"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"async-recursion",
|
"async-recursion",
|
||||||
|
@ -7489,7 +7492,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "turbopack-bench"
|
name = "turbopack-bench"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230716.2#8433a321545de30374b5374320625b92c663f5dc"
|
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230717.2#b0695455647275362c780c85f7e0bcbb3d8d64ec"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"chromiumoxide",
|
"chromiumoxide",
|
||||||
|
@ -7519,7 +7522,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "turbopack-binding"
|
name = "turbopack-binding"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230716.2#8433a321545de30374b5374320625b92c663f5dc"
|
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230717.2#b0695455647275362c780c85f7e0bcbb3d8d64ec"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"auto-hash-map",
|
"auto-hash-map",
|
||||||
"mdxjs",
|
"mdxjs",
|
||||||
|
@ -7561,7 +7564,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "turbopack-build"
|
name = "turbopack-build"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230716.2#8433a321545de30374b5374320625b92c663f5dc"
|
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230717.2#b0695455647275362c780c85f7e0bcbb3d8d64ec"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"indexmap",
|
"indexmap",
|
||||||
|
@ -7581,7 +7584,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "turbopack-cli-utils"
|
name = "turbopack-cli-utils"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230716.2#8433a321545de30374b5374320625b92c663f5dc"
|
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230717.2#b0695455647275362c780c85f7e0bcbb3d8d64ec"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"clap 4.1.11",
|
"clap 4.1.11",
|
||||||
|
@ -7605,7 +7608,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "turbopack-core"
|
name = "turbopack-core"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230716.2#8433a321545de30374b5374320625b92c663f5dc"
|
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230717.2#b0695455647275362c780c85f7e0bcbb3d8d64ec"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"async-trait",
|
"async-trait",
|
||||||
|
@ -7633,7 +7636,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "turbopack-create-test-app"
|
name = "turbopack-create-test-app"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230716.2#8433a321545de30374b5374320625b92c663f5dc"
|
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230717.2#b0695455647275362c780c85f7e0bcbb3d8d64ec"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"clap 4.1.11",
|
"clap 4.1.11",
|
||||||
|
@ -7646,7 +7649,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "turbopack-css"
|
name = "turbopack-css"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230716.2#8433a321545de30374b5374320625b92c663f5dc"
|
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230717.2#b0695455647275362c780c85f7e0bcbb3d8d64ec"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"async-trait",
|
"async-trait",
|
||||||
|
@ -7668,7 +7671,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "turbopack-dev"
|
name = "turbopack-dev"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230716.2#8433a321545de30374b5374320625b92c663f5dc"
|
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230717.2#b0695455647275362c780c85f7e0bcbb3d8d64ec"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"indexmap",
|
"indexmap",
|
||||||
|
@ -7692,7 +7695,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "turbopack-dev-server"
|
name = "turbopack-dev-server"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230716.2#8433a321545de30374b5374320625b92c663f5dc"
|
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230717.2#b0695455647275362c780c85f7e0bcbb3d8d64ec"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"async-compression",
|
"async-compression",
|
||||||
|
@ -7728,7 +7731,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "turbopack-ecmascript"
|
name = "turbopack-ecmascript"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230716.2#8433a321545de30374b5374320625b92c663f5dc"
|
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230717.2#b0695455647275362c780c85f7e0bcbb3d8d64ec"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"async-trait",
|
"async-trait",
|
||||||
|
@ -7761,7 +7764,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "turbopack-ecmascript-plugins"
|
name = "turbopack-ecmascript-plugins"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230716.2#8433a321545de30374b5374320625b92c663f5dc"
|
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230717.2#b0695455647275362c780c85f7e0bcbb3d8d64ec"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"async-trait",
|
"async-trait",
|
||||||
|
@ -7784,7 +7787,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "turbopack-ecmascript-runtime"
|
name = "turbopack-ecmascript-runtime"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230716.2#8433a321545de30374b5374320625b92c663f5dc"
|
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230717.2#b0695455647275362c780c85f7e0bcbb3d8d64ec"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"indoc",
|
"indoc",
|
||||||
|
@ -7801,7 +7804,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "turbopack-env"
|
name = "turbopack-env"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230716.2#8433a321545de30374b5374320625b92c663f5dc"
|
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230717.2#b0695455647275362c780c85f7e0bcbb3d8d64ec"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"indexmap",
|
"indexmap",
|
||||||
|
@ -7817,7 +7820,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "turbopack-image"
|
name = "turbopack-image"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230716.2#8433a321545de30374b5374320625b92c663f5dc"
|
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230717.2#b0695455647275362c780c85f7e0bcbb3d8d64ec"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"base64 0.21.0",
|
"base64 0.21.0",
|
||||||
|
@ -7837,7 +7840,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "turbopack-json"
|
name = "turbopack-json"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230716.2#8433a321545de30374b5374320625b92c663f5dc"
|
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230717.2#b0695455647275362c780c85f7e0bcbb3d8d64ec"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"serde",
|
"serde",
|
||||||
|
@ -7852,7 +7855,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "turbopack-mdx"
|
name = "turbopack-mdx"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230716.2#8433a321545de30374b5374320625b92c663f5dc"
|
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230717.2#b0695455647275362c780c85f7e0bcbb3d8d64ec"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"mdxjs",
|
"mdxjs",
|
||||||
|
@ -7867,7 +7870,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "turbopack-node"
|
name = "turbopack-node"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230716.2#8433a321545de30374b5374320625b92c663f5dc"
|
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230717.2#b0695455647275362c780c85f7e0bcbb3d8d64ec"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"async-stream",
|
"async-stream",
|
||||||
|
@ -7902,7 +7905,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "turbopack-static"
|
name = "turbopack-static"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230716.2#8433a321545de30374b5374320625b92c663f5dc"
|
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230717.2#b0695455647275362c780c85f7e0bcbb3d8d64ec"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"serde",
|
"serde",
|
||||||
|
@ -7918,7 +7921,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "turbopack-swc-utils"
|
name = "turbopack-swc-utils"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230716.2#8433a321545de30374b5374320625b92c663f5dc"
|
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230717.2#b0695455647275362c780c85f7e0bcbb3d8d64ec"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"swc_core",
|
"swc_core",
|
||||||
"turbo-tasks",
|
"turbo-tasks",
|
||||||
|
@ -7929,7 +7932,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "turbopack-test-utils"
|
name = "turbopack-test-utils"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230716.2#8433a321545de30374b5374320625b92c663f5dc"
|
source = "git+https://github.com/vercel/turbo.git?tag=turbopack-230717.2#b0695455647275362c780c85f7e0bcbb3d8d64ec"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
|
@ -7949,7 +7952,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675"
|
checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if 1.0.0",
|
"cfg-if 1.0.0",
|
||||||
"rand 0.8.5",
|
"rand 0.4.6",
|
||||||
"static_assertions",
|
"static_assertions",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -44,11 +44,11 @@ swc_core = { version = "0.79.13" }
|
||||||
testing = { version = "0.33.20" }
|
testing = { version = "0.33.20" }
|
||||||
|
|
||||||
# Turbo crates
|
# Turbo crates
|
||||||
turbopack-binding = { git = "https://github.com/vercel/turbo.git", tag = "turbopack-230716.2" }
|
turbopack-binding = { git = "https://github.com/vercel/turbo.git", tag = "turbopack-230717.2" }
|
||||||
# [TODO]: need to refactor embed_directory! macro usages, as well as resolving turbo_tasks::function, macros..
|
# [TODO]: need to refactor embed_directory! macro usages, as well as resolving turbo_tasks::function, macros..
|
||||||
turbo-tasks = { git = "https://github.com/vercel/turbo.git", tag = "turbopack-230716.2" }
|
turbo-tasks = { git = "https://github.com/vercel/turbo.git", tag = "turbopack-230717.2" }
|
||||||
# [TODO]: need to refactor embed_directory! macro usage in next-core
|
# [TODO]: need to refactor embed_directory! macro usage in next-core
|
||||||
turbo-tasks-fs = { git = "https://github.com/vercel/turbo.git", tag = "turbopack-230716.2" }
|
turbo-tasks-fs = { git = "https://github.com/vercel/turbo.git", tag = "turbopack-230717.2" }
|
||||||
|
|
||||||
# General Deps
|
# General Deps
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,7 @@ indexmap = { workspace = true }
|
||||||
next-core = { workspace = true }
|
next-core = { workspace = true }
|
||||||
once_cell = { workspace = true }
|
once_cell = { workspace = true }
|
||||||
serde = { workspace = true }
|
serde = { workspace = true }
|
||||||
|
serde_json = { workspace = true }
|
||||||
tokio = { workspace = true, features = ["full"] }
|
tokio = { workspace = true, features = ["full"] }
|
||||||
turbopack-binding = { workspace = true, features = [
|
turbopack-binding = { workspace = true, features = [
|
||||||
"__turbo_tasks_memory",
|
"__turbo_tasks_memory",
|
||||||
|
|
|
@ -1,28 +1,349 @@
|
||||||
use next_core::app_structure::Entrypoint;
|
use anyhow::{Context, Result};
|
||||||
|
use next_core::{
|
||||||
|
app_structure::{
|
||||||
|
get_entrypoints, Entrypoint as AppEntrypoint, Entrypoints as AppEntrypoints, LoaderTree,
|
||||||
|
},
|
||||||
|
emit_all_assets,
|
||||||
|
mode::NextMode,
|
||||||
|
next_app::{
|
||||||
|
get_app_client_references_chunks, get_app_client_shared_chunks, get_app_page_entry,
|
||||||
|
get_app_route_entry, AppEntry,
|
||||||
|
},
|
||||||
|
next_client::{
|
||||||
|
get_client_module_options_context, get_client_resolve_options_context,
|
||||||
|
get_client_runtime_entries, ClientContextType,
|
||||||
|
},
|
||||||
|
next_client_reference::{
|
||||||
|
ClientReferenceGraph, ClientReferenceType, NextEcmascriptClientReferenceTransition,
|
||||||
|
},
|
||||||
|
next_dynamic::{NextDynamicEntries, NextDynamicTransition},
|
||||||
|
next_manifests::{
|
||||||
|
AppBuildManifest, AppPathsManifest, BuildManifest, ClientReferenceManifest, PagesManifest,
|
||||||
|
},
|
||||||
|
next_server::{
|
||||||
|
get_server_module_options_context, get_server_resolve_options_context,
|
||||||
|
get_server_runtime_entries, ServerContextType,
|
||||||
|
},
|
||||||
|
};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use turbo_tasks::{trace::TraceRawVcs, Completion, Vc};
|
use turbo_tasks::{trace::TraceRawVcs, Completion, TryJoinIterExt, Value, Vc};
|
||||||
|
use turbopack_binding::{
|
||||||
|
turbo::{
|
||||||
|
tasks_env::{CustomProcessEnv, ProcessEnv},
|
||||||
|
tasks_fs::{File, FileSystemPath},
|
||||||
|
},
|
||||||
|
turbopack::{
|
||||||
|
core::{
|
||||||
|
asset::{Asset, AssetContent},
|
||||||
|
changed::any_content_changed_of_output_assets,
|
||||||
|
chunk::EvaluatableAssets,
|
||||||
|
file_source::FileSource,
|
||||||
|
output::{OutputAsset, OutputAssets},
|
||||||
|
raw_output::RawOutput,
|
||||||
|
virtual_source::VirtualSource,
|
||||||
|
},
|
||||||
|
turbopack::{
|
||||||
|
module_options::ModuleOptionsContext, resolve_options_context::ResolveOptionsContext,
|
||||||
|
transition::ContextTransition, ModuleAssetContext,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
use crate::route::{Endpoint, Route, WrittenEndpoint};
|
use crate::{
|
||||||
|
project::Project,
|
||||||
|
route::{Endpoint, Route, Routes, WrittenEndpoint},
|
||||||
|
};
|
||||||
|
|
||||||
|
#[turbo_tasks::value]
|
||||||
|
pub struct AppProject {
|
||||||
|
project: Vc<Project>,
|
||||||
|
app_dir: Vc<FileSystemPath>,
|
||||||
|
mode: NextMode,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[turbo_tasks::value(transparent)]
|
||||||
|
pub struct OptionAppProject(Option<Vc<AppProject>>);
|
||||||
|
|
||||||
|
impl AppProject {
|
||||||
|
fn client_ty(self: Vc<Self>) -> ClientContextType {
|
||||||
|
ClientContextType::App {
|
||||||
|
app_dir: self.app_dir(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn rsc_ty(self: Vc<Self>) -> ServerContextType {
|
||||||
|
ServerContextType::AppRSC {
|
||||||
|
app_dir: self.app_dir(),
|
||||||
|
client_transition: Some(Vc::upcast(self.client_transition())),
|
||||||
|
ecmascript_client_reference_transition_name: Some(self.client_transition_name()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn ssr_ty(self: Vc<Self>) -> ServerContextType {
|
||||||
|
ServerContextType::AppSSR {
|
||||||
|
app_dir: self.app_dir(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const ECMASCRIPT_CLIENT_TRANSITION_NAME: &str = "next-ecmascript-client-reference";
|
||||||
|
|
||||||
|
#[turbo_tasks::value_impl]
|
||||||
|
impl AppProject {
|
||||||
|
#[turbo_tasks::function]
|
||||||
|
pub fn new(project: Vc<Project>, app_dir: Vc<FileSystemPath>, mode: NextMode) -> Vc<Self> {
|
||||||
|
AppProject {
|
||||||
|
project,
|
||||||
|
app_dir,
|
||||||
|
mode,
|
||||||
|
}
|
||||||
|
.cell()
|
||||||
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
pub async fn app_entry_point_to_route(entrypoint: Entrypoint) -> Vc<Route> {
|
fn project(&self) -> Vc<Project> {
|
||||||
|
self.project
|
||||||
|
}
|
||||||
|
|
||||||
|
#[turbo_tasks::function]
|
||||||
|
fn app_dir(&self) -> Vc<FileSystemPath> {
|
||||||
|
self.app_dir
|
||||||
|
}
|
||||||
|
|
||||||
|
#[turbo_tasks::function]
|
||||||
|
fn app_entrypoints(&self) -> Vc<AppEntrypoints> {
|
||||||
|
get_entrypoints(self.app_dir, self.project.next_config().page_extensions())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[turbo_tasks::function]
|
||||||
|
async fn client_module_options_context(self: Vc<Self>) -> Result<Vc<ModuleOptionsContext>> {
|
||||||
|
let this = self.await?;
|
||||||
|
Ok(get_client_module_options_context(
|
||||||
|
self.project().project_path(),
|
||||||
|
self.project().execution_context(),
|
||||||
|
self.project().client_compile_time_info().environment(),
|
||||||
|
Value::new(self.client_ty()),
|
||||||
|
this.mode,
|
||||||
|
self.project().next_config(),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[turbo_tasks::function]
|
||||||
|
async fn client_resolve_options_context(self: Vc<Self>) -> Result<Vc<ResolveOptionsContext>> {
|
||||||
|
let this = self.await?;
|
||||||
|
Ok(get_client_resolve_options_context(
|
||||||
|
self.project().project_path(),
|
||||||
|
Value::new(self.client_ty()),
|
||||||
|
this.mode,
|
||||||
|
self.project().next_config(),
|
||||||
|
self.project().execution_context(),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[turbo_tasks::function]
|
||||||
|
fn client_transition_name(self: Vc<Self>) -> Vc<String> {
|
||||||
|
Vc::cell(ECMASCRIPT_CLIENT_TRANSITION_NAME.to_string())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[turbo_tasks::function]
|
||||||
|
fn client_transition(self: Vc<Self>) -> Vc<ContextTransition> {
|
||||||
|
ContextTransition::new(
|
||||||
|
self.project().client_compile_time_info(),
|
||||||
|
self.client_module_options_context(),
|
||||||
|
self.client_resolve_options_context(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[turbo_tasks::function]
|
||||||
|
async fn rsc_module_options_context(self: Vc<Self>) -> Result<Vc<ModuleOptionsContext>> {
|
||||||
|
let this = self.await?;
|
||||||
|
Ok(get_server_module_options_context(
|
||||||
|
self.project().project_path(),
|
||||||
|
self.project().execution_context(),
|
||||||
|
Value::new(self.rsc_ty()),
|
||||||
|
this.mode,
|
||||||
|
self.project().next_config(),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[turbo_tasks::function]
|
||||||
|
async fn rsc_resolve_options_context(self: Vc<Self>) -> Result<Vc<ResolveOptionsContext>> {
|
||||||
|
let this = self.await?;
|
||||||
|
Ok(get_server_resolve_options_context(
|
||||||
|
self.project().project_path(),
|
||||||
|
Value::new(self.rsc_ty()),
|
||||||
|
this.mode,
|
||||||
|
self.project().next_config(),
|
||||||
|
self.project().execution_context(),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[turbo_tasks::function]
|
||||||
|
fn rsc_module_context(self: Vc<Self>) -> Vc<ModuleAssetContext> {
|
||||||
|
let transitions = [
|
||||||
|
(
|
||||||
|
ECMASCRIPT_CLIENT_TRANSITION_NAME.to_string(),
|
||||||
|
Vc::upcast(NextEcmascriptClientReferenceTransition::new(
|
||||||
|
self.client_transition(),
|
||||||
|
self.ssr_transition(),
|
||||||
|
)),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"next-dynamic".to_string(),
|
||||||
|
Vc::upcast(NextDynamicTransition::new(self.client_transition())),
|
||||||
|
),
|
||||||
|
]
|
||||||
|
.into_iter()
|
||||||
|
.collect();
|
||||||
|
ModuleAssetContext::new(
|
||||||
|
Vc::cell(transitions),
|
||||||
|
self.project().server_compile_time_info(),
|
||||||
|
self.rsc_module_options_context(),
|
||||||
|
self.rsc_resolve_options_context(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[turbo_tasks::function]
|
||||||
|
fn client_module_context(self: Vc<Self>) -> Vc<ModuleAssetContext> {
|
||||||
|
ModuleAssetContext::new(
|
||||||
|
Vc::cell(Default::default()),
|
||||||
|
self.project().client_compile_time_info(),
|
||||||
|
self.client_module_options_context(),
|
||||||
|
self.client_resolve_options_context(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[turbo_tasks::function]
|
||||||
|
async fn ssr_module_options_context(self: Vc<Self>) -> Result<Vc<ModuleOptionsContext>> {
|
||||||
|
let this = self.await?;
|
||||||
|
Ok(get_server_module_options_context(
|
||||||
|
self.project().project_path(),
|
||||||
|
self.project().execution_context(),
|
||||||
|
Value::new(self.ssr_ty()),
|
||||||
|
this.mode,
|
||||||
|
self.project().next_config(),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[turbo_tasks::function]
|
||||||
|
async fn ssr_resolve_options_context(self: Vc<Self>) -> Result<Vc<ResolveOptionsContext>> {
|
||||||
|
let this = self.await?;
|
||||||
|
Ok(get_server_resolve_options_context(
|
||||||
|
self.project().project_path(),
|
||||||
|
Value::new(self.ssr_ty()),
|
||||||
|
this.mode,
|
||||||
|
self.project().next_config(),
|
||||||
|
self.project().execution_context(),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[turbo_tasks::function]
|
||||||
|
fn ssr_transition(self: Vc<Self>) -> Vc<ContextTransition> {
|
||||||
|
ContextTransition::new(
|
||||||
|
self.project().server_compile_time_info(),
|
||||||
|
self.ssr_module_options_context(),
|
||||||
|
self.ssr_resolve_options_context(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[turbo_tasks::function]
|
||||||
|
async fn rsc_runtime_entries(self: Vc<Self>) -> Result<Vc<EvaluatableAssets>> {
|
||||||
|
let this = self.await?;
|
||||||
|
Ok(get_server_runtime_entries(
|
||||||
|
self.project().project_path(),
|
||||||
|
// TODO(alexkirsz) Should we pass env here or EnvMap::empty, as is done in
|
||||||
|
// app_source?
|
||||||
|
self.project().env(),
|
||||||
|
Value::new(self.rsc_ty()),
|
||||||
|
this.mode,
|
||||||
|
self.project().next_config(),
|
||||||
|
)
|
||||||
|
.resolve_entries(Vc::upcast(self.rsc_module_context())))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[turbo_tasks::function]
|
||||||
|
fn client_env(self: Vc<Self>) -> Vc<Box<dyn ProcessEnv>> {
|
||||||
|
Vc::upcast(CustomProcessEnv::new(
|
||||||
|
self.project().env(),
|
||||||
|
self.project().next_config().env(),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[turbo_tasks::function]
|
||||||
|
async fn client_runtime_entries(self: Vc<Self>) -> Result<Vc<EvaluatableAssets>> {
|
||||||
|
let this = self.await?;
|
||||||
|
Ok(get_client_runtime_entries(
|
||||||
|
self.project().project_path(),
|
||||||
|
self.client_env(),
|
||||||
|
Value::new(self.client_ty()),
|
||||||
|
this.mode,
|
||||||
|
self.project().next_config(),
|
||||||
|
self.project().execution_context(),
|
||||||
|
)
|
||||||
|
.resolve_entries(Vc::upcast(self.client_module_context())))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[turbo_tasks::function]
|
||||||
|
pub async fn routes(self: Vc<Self>) -> Result<Vc<Routes>> {
|
||||||
|
let app_entrypoints = self.app_entrypoints();
|
||||||
|
Ok(Vc::cell(
|
||||||
|
app_entrypoints
|
||||||
|
.await?
|
||||||
|
.iter()
|
||||||
|
.map(|(pathname, app_entrypoint)| async {
|
||||||
|
Ok((
|
||||||
|
pathname.clone(),
|
||||||
|
*app_entry_point_to_route(self, *app_entrypoint, pathname.clone()).await?,
|
||||||
|
))
|
||||||
|
})
|
||||||
|
.try_join()
|
||||||
|
.await?
|
||||||
|
.into_iter()
|
||||||
|
.collect(),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[turbo_tasks::function]
|
||||||
|
pub async fn app_entry_point_to_route(
|
||||||
|
app_project: Vc<AppProject>,
|
||||||
|
entrypoint: AppEntrypoint,
|
||||||
|
pathname: String,
|
||||||
|
) -> Vc<Route> {
|
||||||
match entrypoint {
|
match entrypoint {
|
||||||
Entrypoint::AppPage { .. } => Route::AppPage {
|
AppEntrypoint::AppPage { loader_tree } => Route::AppPage {
|
||||||
html_endpoint: Vc::upcast(
|
html_endpoint: Vc::upcast(
|
||||||
AppPageEndpoint {
|
AppEndpoint {
|
||||||
|
ty: AppEndpointType::Page {
|
||||||
ty: AppPageEndpointType::Html,
|
ty: AppPageEndpointType::Html,
|
||||||
|
loader_tree,
|
||||||
|
},
|
||||||
|
app_project,
|
||||||
|
pathname: pathname.clone(),
|
||||||
}
|
}
|
||||||
.cell(),
|
.cell(),
|
||||||
),
|
),
|
||||||
rsc_endpoint: Vc::upcast(
|
rsc_endpoint: Vc::upcast(
|
||||||
AppPageEndpoint {
|
AppEndpoint {
|
||||||
|
ty: AppEndpointType::Page {
|
||||||
ty: AppPageEndpointType::Rsc,
|
ty: AppPageEndpointType::Rsc,
|
||||||
|
loader_tree,
|
||||||
|
},
|
||||||
|
app_project,
|
||||||
|
pathname,
|
||||||
}
|
}
|
||||||
.cell(),
|
.cell(),
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
Entrypoint::AppRoute { .. } => Route::AppRoute {
|
AppEntrypoint::AppRoute { path } => Route::AppRoute {
|
||||||
endpoint: Vc::upcast(AppRouteEndpoint.cell()),
|
endpoint: Vc::upcast(
|
||||||
|
AppEndpoint {
|
||||||
|
ty: AppEndpointType::Route { path },
|
||||||
|
app_project,
|
||||||
|
pathname: pathname.clone(),
|
||||||
|
}
|
||||||
|
.cell(),
|
||||||
|
),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
.cell()
|
.cell()
|
||||||
|
@ -34,36 +355,288 @@ enum AppPageEndpointType {
|
||||||
Rsc,
|
Rsc,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::value]
|
#[derive(Copy, Clone, Serialize, Deserialize, PartialEq, Eq, Debug, TraceRawVcs)]
|
||||||
struct AppPageEndpoint {
|
enum AppEndpointType {
|
||||||
|
Page {
|
||||||
ty: AppPageEndpointType,
|
ty: AppPageEndpointType,
|
||||||
|
loader_tree: Vc<LoaderTree>,
|
||||||
|
},
|
||||||
|
Route {
|
||||||
|
path: Vc<FileSystemPath>,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
#[turbo_tasks::value]
|
||||||
|
struct AppEndpoint {
|
||||||
|
ty: AppEndpointType,
|
||||||
|
app_project: Vc<AppProject>,
|
||||||
|
pathname: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::value_impl]
|
#[turbo_tasks::value_impl]
|
||||||
impl Endpoint for AppPageEndpoint {
|
impl AppEndpoint {
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn write_to_disk(&self) -> Vc<WrittenEndpoint> {
|
fn client_relative_path(&self) -> Vc<FileSystemPath> {
|
||||||
todo!()
|
self.app_project
|
||||||
|
.project()
|
||||||
|
.client_root()
|
||||||
|
.join("_next".to_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn changed(&self) -> Vc<Completion> {
|
fn app_page_entry(&self, loader_tree: Vc<LoaderTree>) -> Vc<AppEntry> {
|
||||||
todo!()
|
get_app_page_entry(
|
||||||
|
self.app_project.rsc_module_context(),
|
||||||
|
loader_tree,
|
||||||
|
self.app_project.app_dir(),
|
||||||
|
self.pathname.clone(),
|
||||||
|
self.app_project.project().project_path(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[turbo_tasks::function]
|
||||||
|
fn app_route_entry(&self, path: Vc<FileSystemPath>) -> Vc<AppEntry> {
|
||||||
|
get_app_route_entry(
|
||||||
|
self.app_project.rsc_module_context(),
|
||||||
|
Vc::upcast(FileSource::new(path)),
|
||||||
|
self.pathname.clone(),
|
||||||
|
self.app_project.project().project_path(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[turbo_tasks::function]
|
||||||
|
async fn output(self: Vc<Self>) -> Result<Vc<AppEndpointOutput>> {
|
||||||
|
let this = self.await?;
|
||||||
|
|
||||||
|
let app_entry = match this.ty {
|
||||||
|
AppEndpointType::Page { ty: _, loader_tree } => self.app_page_entry(loader_tree),
|
||||||
|
// NOTE(alexkirsz) For routes, technically, a lot of the following code is not needed,
|
||||||
|
// as we know we won't have any client references. However, for now, for simplicity's
|
||||||
|
// sake, we just do the same thing as for pages.
|
||||||
|
AppEndpointType::Route { path } => self.app_route_entry(path),
|
||||||
|
};
|
||||||
|
|
||||||
|
let node_root = this.app_project.project().node_root();
|
||||||
|
|
||||||
|
let client_relative_path = self.client_relative_path();
|
||||||
|
let client_relative_path_ref = client_relative_path.await?;
|
||||||
|
|
||||||
|
let server_path = node_root.join("server".to_string());
|
||||||
|
|
||||||
|
let mut output_assets = vec![];
|
||||||
|
|
||||||
|
let client_shared_chunks = get_app_client_shared_chunks(
|
||||||
|
this.app_project.client_runtime_entries(),
|
||||||
|
this.app_project.project().client_chunking_context(),
|
||||||
|
);
|
||||||
|
|
||||||
|
let mut client_shared_chunks_paths = vec![];
|
||||||
|
for chunk in client_shared_chunks.await?.iter().copied() {
|
||||||
|
output_assets.push(chunk);
|
||||||
|
|
||||||
|
let chunk_path = chunk.ident().path().await?;
|
||||||
|
if chunk_path.extension_ref() == Some("js") {
|
||||||
|
if let Some(chunk_path) = client_relative_path_ref.get_path_to(&chunk_path) {
|
||||||
|
client_shared_chunks_paths.push(chunk_path.to_string());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let app_entry = app_entry.await?;
|
||||||
|
let rsc_entry = app_entry.rsc_entry;
|
||||||
|
|
||||||
|
let rsc_entry_asset = Vc::upcast(rsc_entry);
|
||||||
|
let client_reference_graph = ClientReferenceGraph::new(Vc::cell(vec![rsc_entry_asset]));
|
||||||
|
let client_reference_types = client_reference_graph.types();
|
||||||
|
let client_references = client_reference_graph.entry(rsc_entry_asset);
|
||||||
|
|
||||||
|
let app_ssr_entries: Vec<_> = client_reference_types
|
||||||
|
.await?
|
||||||
|
.iter()
|
||||||
|
.map(|client_reference_ty| async move {
|
||||||
|
let ClientReferenceType::EcmascriptClientReference(entry) = client_reference_ty
|
||||||
|
else {
|
||||||
|
return Ok(None);
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(Some(entry.await?.ssr_module))
|
||||||
|
})
|
||||||
|
.try_join()
|
||||||
|
.await?
|
||||||
|
.into_iter()
|
||||||
|
.flatten()
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let app_node_entries: Vec<_> = app_ssr_entries.iter().copied().chain([rsc_entry]).collect();
|
||||||
|
|
||||||
|
// TODO(alexkirsz) Handle dynamic entries and dynamic chunks.
|
||||||
|
let _dynamic_entries = NextDynamicEntries::from_entries(Vc::cell(
|
||||||
|
app_node_entries.iter().copied().map(Vc::upcast).collect(),
|
||||||
|
))
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
let rsc_chunk = this
|
||||||
|
.app_project
|
||||||
|
.project()
|
||||||
|
.rsc_chunking_context()
|
||||||
|
.entry_chunk(
|
||||||
|
server_path.join(format!(
|
||||||
|
"app/{original_name}.js",
|
||||||
|
original_name = app_entry.original_name
|
||||||
|
)),
|
||||||
|
app_entry.rsc_entry,
|
||||||
|
this.app_project.rsc_runtime_entries(),
|
||||||
|
);
|
||||||
|
output_assets.push(rsc_chunk);
|
||||||
|
|
||||||
|
let app_entry_client_references = client_reference_graph
|
||||||
|
.entry(Vc::upcast(app_entry.rsc_entry))
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
let client_references_chunks = get_app_client_references_chunks(
|
||||||
|
client_reference_types,
|
||||||
|
this.app_project.project().client_chunking_context(),
|
||||||
|
this.app_project.project().ssr_chunking_context(),
|
||||||
|
);
|
||||||
|
let client_references_chunks_ref = client_references_chunks.await?;
|
||||||
|
|
||||||
|
let mut entry_client_chunks = vec![];
|
||||||
|
// TODO(alexkirsz) In which manifest does this go?
|
||||||
|
let mut entry_ssr_chunks = vec![];
|
||||||
|
for client_reference in app_entry_client_references.iter() {
|
||||||
|
let client_reference_chunks = client_references_chunks_ref
|
||||||
|
.get(client_reference.ty())
|
||||||
|
.expect("client reference should have corresponding chunks");
|
||||||
|
entry_client_chunks
|
||||||
|
.extend(client_reference_chunks.client_chunks.await?.iter().copied());
|
||||||
|
entry_ssr_chunks.extend(client_reference_chunks.ssr_chunks.await?.iter().copied());
|
||||||
|
}
|
||||||
|
|
||||||
|
output_assets.extend(entry_client_chunks.iter().copied());
|
||||||
|
output_assets.extend(entry_ssr_chunks.iter().copied());
|
||||||
|
|
||||||
|
let entry_client_chunks_paths = entry_client_chunks
|
||||||
|
.iter()
|
||||||
|
.map(|chunk| chunk.ident().path())
|
||||||
|
.try_join()
|
||||||
|
.await?;
|
||||||
|
let mut entry_client_chunks_paths: Vec<_> = entry_client_chunks_paths
|
||||||
|
.iter()
|
||||||
|
.map(|path| {
|
||||||
|
client_relative_path_ref
|
||||||
|
.get_path_to(path)
|
||||||
|
.expect("asset path should be inside client root")
|
||||||
|
.to_string()
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
entry_client_chunks_paths.extend(client_shared_chunks_paths.iter().cloned());
|
||||||
|
|
||||||
|
let app_build_manifest = AppBuildManifest {
|
||||||
|
pages: [(app_entry.original_name.clone(), entry_client_chunks_paths)]
|
||||||
|
.into_iter()
|
||||||
|
.collect(),
|
||||||
|
};
|
||||||
|
let app_build_manifest_output = Vc::upcast(RawOutput::new(Vc::upcast(VirtualSource::new(
|
||||||
|
node_root.join("server/app-build-manifest.json".to_string()),
|
||||||
|
AssetContent::file(
|
||||||
|
File::from(serde_json::to_string_pretty(&app_build_manifest)?).into(),
|
||||||
|
),
|
||||||
|
))));
|
||||||
|
output_assets.push(app_build_manifest_output);
|
||||||
|
|
||||||
|
let app_paths_manifest = AppPathsManifest {
|
||||||
|
node_server_app_paths: PagesManifest {
|
||||||
|
pages: [(
|
||||||
|
app_entry.original_name.clone(),
|
||||||
|
server_path
|
||||||
|
.await?
|
||||||
|
.get_path_to(&*rsc_chunk.ident().path().await?)
|
||||||
|
.expect("RSC chunk path should be within app paths manifest directory")
|
||||||
|
.to_string(),
|
||||||
|
)]
|
||||||
|
.into_iter()
|
||||||
|
.collect(),
|
||||||
|
},
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
let app_paths_manifest_output = Vc::upcast(RawOutput::new(Vc::upcast(VirtualSource::new(
|
||||||
|
node_root.join("server/app-paths-manifest.json".to_string()),
|
||||||
|
AssetContent::file(
|
||||||
|
File::from(serde_json::to_string_pretty(&app_paths_manifest)?).into(),
|
||||||
|
),
|
||||||
|
))));
|
||||||
|
output_assets.push(app_paths_manifest_output);
|
||||||
|
|
||||||
|
let build_manifest = BuildManifest {
|
||||||
|
root_main_files: client_shared_chunks_paths,
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
let build_manifest_output = Vc::upcast(RawOutput::new(Vc::upcast(VirtualSource::new(
|
||||||
|
node_root.join("build-manifest.json".to_string()),
|
||||||
|
AssetContent::file(File::from(serde_json::to_string_pretty(&build_manifest)?).into()),
|
||||||
|
))));
|
||||||
|
output_assets.push(build_manifest_output);
|
||||||
|
|
||||||
|
let entry_manifest = ClientReferenceManifest::build_output(
|
||||||
|
node_root,
|
||||||
|
client_relative_path,
|
||||||
|
app_entry.original_name.clone(),
|
||||||
|
client_references,
|
||||||
|
client_references_chunks,
|
||||||
|
this.app_project.project().client_chunking_context(),
|
||||||
|
Vc::upcast(this.app_project.project().ssr_chunking_context()),
|
||||||
|
);
|
||||||
|
output_assets.push(entry_manifest);
|
||||||
|
|
||||||
|
Ok(AppEndpointOutput {
|
||||||
|
rsc_chunk,
|
||||||
|
output_assets: Vc::cell(output_assets),
|
||||||
|
}
|
||||||
|
.cell())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[turbo_tasks::value_impl]
|
||||||
|
impl Endpoint for AppEndpoint {
|
||||||
|
#[turbo_tasks::function]
|
||||||
|
async fn write_to_disk(self: Vc<Self>) -> Result<Vc<WrittenEndpoint>> {
|
||||||
|
let output = self.output();
|
||||||
|
|
||||||
|
let this = self.await?;
|
||||||
|
let node_root = this.app_project.project().node_root();
|
||||||
|
|
||||||
|
let output = output.await?;
|
||||||
|
let node_root_ref = node_root.await?;
|
||||||
|
|
||||||
|
emit_all_assets(
|
||||||
|
output.output_assets,
|
||||||
|
this.app_project.project().node_root(),
|
||||||
|
self.client_relative_path(),
|
||||||
|
this.app_project.project().node_root(),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
Ok(WrittenEndpoint {
|
||||||
|
server_entry_path: node_root_ref
|
||||||
|
.get_path_to(&*output.rsc_chunk.ident().path().await?)
|
||||||
|
.context("rsc chunk entry path must be inside the node root")?
|
||||||
|
.to_string(),
|
||||||
|
server_paths: vec![],
|
||||||
|
}
|
||||||
|
.cell())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[turbo_tasks::function]
|
||||||
|
async fn changed(self: Vc<Self>) -> Result<Vc<Completion>> {
|
||||||
|
let output = self.output();
|
||||||
|
Ok(any_content_changed_of_output_assets(
|
||||||
|
output.await?.output_assets,
|
||||||
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::value]
|
#[turbo_tasks::value]
|
||||||
struct AppRouteEndpoint;
|
struct AppEndpointOutput {
|
||||||
|
rsc_chunk: Vc<Box<dyn OutputAsset>>,
|
||||||
#[turbo_tasks::value_impl]
|
output_assets: Vc<OutputAssets>,
|
||||||
impl Endpoint for AppRouteEndpoint {
|
|
||||||
#[turbo_tasks::function]
|
|
||||||
fn write_to_disk(&self) -> Vc<WrittenEndpoint> {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
|
||||||
fn changed(&self) -> Vc<Completion> {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
9
packages/next-swc/crates/next-api/src/entrypoints.rs
Normal file
9
packages/next-swc/crates/next-api/src/entrypoints.rs
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
use indexmap::IndexMap;
|
||||||
|
|
||||||
|
use crate::{project::Middleware, route::Route};
|
||||||
|
|
||||||
|
#[turbo_tasks::value(shared)]
|
||||||
|
pub struct Entrypoints {
|
||||||
|
pub routes: IndexMap<String, Route>,
|
||||||
|
pub middleware: Option<Middleware>,
|
||||||
|
}
|
|
@ -3,6 +3,7 @@
|
||||||
#![feature(async_fn_in_trait)]
|
#![feature(async_fn_in_trait)]
|
||||||
|
|
||||||
mod app;
|
mod app;
|
||||||
|
mod entrypoints;
|
||||||
mod pages;
|
mod pages;
|
||||||
pub mod project;
|
pub mod project;
|
||||||
pub mod route;
|
pub mod route;
|
||||||
|
|
|
@ -2,16 +2,28 @@ use anyhow::{bail, Context, Result};
|
||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
use next_core::{
|
use next_core::{
|
||||||
create_page_loader_entry_module, emit_all_assets, get_asset_path_from_pathname,
|
create_page_loader_entry_module, emit_all_assets, get_asset_path_from_pathname,
|
||||||
pages_structure::{PagesDirectoryStructure, PagesStructure, PagesStructureItem},
|
mode::NextMode,
|
||||||
|
next_client::{
|
||||||
|
get_client_module_options_context, get_client_resolve_options_context,
|
||||||
|
get_client_runtime_entries, ClientContextType,
|
||||||
|
},
|
||||||
|
next_dynamic::NextDynamicTransition,
|
||||||
|
next_server::{
|
||||||
|
get_server_module_options_context, get_server_resolve_options_context,
|
||||||
|
get_server_runtime_entries, ServerContextType,
|
||||||
|
},
|
||||||
|
pages_structure::{
|
||||||
|
find_pages_structure, PagesDirectoryStructure, PagesStructure, PagesStructureItem,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
use turbo_tasks::{Completion, Completions, Value, Vc};
|
use turbo_tasks::{Completion, Completions, Value, Vc};
|
||||||
use turbopack_binding::{
|
use turbopack_binding::{
|
||||||
turbo::tasks_fs::FileSystemPath,
|
turbo::tasks_fs::{FileSystem, FileSystemPath, VirtualFileSystem},
|
||||||
turbopack::{
|
turbopack::{
|
||||||
core::{
|
core::{
|
||||||
asset::Asset,
|
asset::Asset,
|
||||||
changed::{any_content_changed, any_content_changed_of_output_assets},
|
changed::{any_content_changed, any_content_changed_of_output_assets},
|
||||||
chunk::{ChunkableModule, ChunkingContext},
|
chunk::{ChunkableModule, ChunkingContext, EvaluatableAssets},
|
||||||
context::AssetContext,
|
context::AssetContext,
|
||||||
file_source::FileSource,
|
file_source::FileSource,
|
||||||
output::{OutputAsset, OutputAssets},
|
output::{OutputAsset, OutputAssets},
|
||||||
|
@ -19,6 +31,12 @@ use turbopack_binding::{
|
||||||
source::Source,
|
source::Source,
|
||||||
},
|
},
|
||||||
ecmascript::EcmascriptModuleAsset,
|
ecmascript::EcmascriptModuleAsset,
|
||||||
|
turbopack::{
|
||||||
|
module_options::ModuleOptionsContext,
|
||||||
|
resolve_options_context::ResolveOptionsContext,
|
||||||
|
transition::{ContextTransition, TransitionsByName},
|
||||||
|
ModuleAssetContext,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -27,12 +45,22 @@ use crate::{
|
||||||
route::{Endpoint, Route, Routes, WrittenEndpoint},
|
route::{Endpoint, Route, Routes, WrittenEndpoint},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::value]
|
||||||
pub async fn get_pages_routes(
|
pub struct PagesProject {
|
||||||
project: Vc<Project>,
|
project: Vc<Project>,
|
||||||
page_structure: Vc<PagesStructure>,
|
mode: NextMode,
|
||||||
) -> Result<Vc<Routes>> {
|
}
|
||||||
let PagesStructure { api, pages, .. } = *page_structure.await?;
|
|
||||||
|
#[turbo_tasks::value_impl]
|
||||||
|
impl PagesProject {
|
||||||
|
#[turbo_tasks::function]
|
||||||
|
pub async fn new(project: Vc<Project>, mode: NextMode) -> Result<Vc<Self>> {
|
||||||
|
Ok(PagesProject { project, mode }.cell())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[turbo_tasks::function]
|
||||||
|
pub async fn routes(self: Vc<Self>) -> Result<Vc<Routes>> {
|
||||||
|
let PagesStructure { api, pages, .. } = &*self.pages_structure().await?;
|
||||||
let mut routes = IndexMap::new();
|
let mut routes = IndexMap::new();
|
||||||
async fn add_dir_to_routes(
|
async fn add_dir_to_routes(
|
||||||
routes: &mut IndexMap<String, Route>,
|
routes: &mut IndexMap<String, Route>,
|
||||||
|
@ -66,24 +94,24 @@ pub async fn get_pages_routes(
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
if let Some(api) = api {
|
if let Some(api) = api {
|
||||||
add_dir_to_routes(&mut routes, api, |pathname, original_name, path| {
|
add_dir_to_routes(&mut routes, *api, |pathname, original_name, path| {
|
||||||
Route::PageApi {
|
Route::PageApi {
|
||||||
endpoint: Vc::upcast(ApiEndpoint::new(project, pathname, original_name, path)),
|
endpoint: Vc::upcast(PageApiEndpoint::new(self, pathname, original_name, path)),
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.await?;
|
.await?;
|
||||||
}
|
}
|
||||||
if let Some(page) = pages {
|
if let Some(page) = pages {
|
||||||
add_dir_to_routes(&mut routes, page, |pathname, original_name, path| {
|
add_dir_to_routes(&mut routes, *page, |pathname, original_name, path| {
|
||||||
Route::Page {
|
Route::Page {
|
||||||
html_endpoint: Vc::upcast(PageHtmlEndpoint::new(
|
html_endpoint: Vc::upcast(PageHtmlEndpoint::new(
|
||||||
project,
|
self,
|
||||||
pathname,
|
pathname,
|
||||||
original_name,
|
original_name,
|
||||||
path,
|
path,
|
||||||
)),
|
)),
|
||||||
data_endpoint: Vc::upcast(PageDataEndpoint::new(
|
data_endpoint: Vc::upcast(PageDataEndpoint::new(
|
||||||
project,
|
self,
|
||||||
pathname,
|
pathname,
|
||||||
original_name,
|
original_name,
|
||||||
path,
|
path,
|
||||||
|
@ -95,9 +123,188 @@ pub async fn get_pages_routes(
|
||||||
Ok(Vc::cell(routes))
|
Ok(Vc::cell(routes))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[turbo_tasks::function]
|
||||||
|
fn project(&self) -> Vc<Project> {
|
||||||
|
self.project
|
||||||
|
}
|
||||||
|
|
||||||
|
#[turbo_tasks::function]
|
||||||
|
fn pages_structure(&self) -> Vc<PagesStructure> {
|
||||||
|
let next_router_fs = Vc::upcast::<Box<dyn FileSystem>>(VirtualFileSystem::new());
|
||||||
|
let next_router_root = next_router_fs.root();
|
||||||
|
find_pages_structure(
|
||||||
|
self.project.project_path(),
|
||||||
|
next_router_root,
|
||||||
|
self.project.next_config().page_extensions(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[turbo_tasks::function]
|
||||||
|
async fn pages_dir(self: Vc<Self>) -> Result<Vc<FileSystemPath>> {
|
||||||
|
Ok(if let Some(pages) = self.pages_structure().await?.pages {
|
||||||
|
pages.project_path()
|
||||||
|
} else {
|
||||||
|
self.project().project_path().join("pages".to_string())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
#[turbo_tasks::function]
|
||||||
|
fn transitions(self: Vc<Self>) -> Vc<TransitionsByName> {
|
||||||
|
Vc::cell(
|
||||||
|
[(
|
||||||
|
"next-dynamic".to_string(),
|
||||||
|
Vc::upcast(NextDynamicTransition::new(self.client_transition())),
|
||||||
|
)]
|
||||||
|
.into_iter()
|
||||||
|
.collect(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[turbo_tasks::function]
|
||||||
|
fn client_transition(self: Vc<Self>) -> Vc<ContextTransition> {
|
||||||
|
ContextTransition::new(
|
||||||
|
self.project().client_compile_time_info(),
|
||||||
|
self.client_module_options_context(),
|
||||||
|
self.client_resolve_options_context(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[turbo_tasks::function]
|
||||||
|
async fn client_module_options_context(self: Vc<Self>) -> Result<Vc<ModuleOptionsContext>> {
|
||||||
|
let this = self.await?;
|
||||||
|
Ok(get_client_module_options_context(
|
||||||
|
self.project().project_path(),
|
||||||
|
self.project().execution_context(),
|
||||||
|
self.project().client_compile_time_info().environment(),
|
||||||
|
Value::new(ClientContextType::Pages {
|
||||||
|
pages_dir: self.pages_dir(),
|
||||||
|
}),
|
||||||
|
this.mode,
|
||||||
|
self.project().next_config(),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[turbo_tasks::function]
|
||||||
|
async fn client_resolve_options_context(self: Vc<Self>) -> Result<Vc<ResolveOptionsContext>> {
|
||||||
|
let this = self.await?;
|
||||||
|
Ok(get_client_resolve_options_context(
|
||||||
|
self.project().project_path(),
|
||||||
|
Value::new(ClientContextType::Pages {
|
||||||
|
pages_dir: self.pages_dir(),
|
||||||
|
}),
|
||||||
|
this.mode,
|
||||||
|
self.project().next_config(),
|
||||||
|
self.project().execution_context(),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[turbo_tasks::function]
|
||||||
|
pub(super) fn client_module_context(self: Vc<Self>) -> Vc<Box<dyn AssetContext>> {
|
||||||
|
Vc::upcast(ModuleAssetContext::new(
|
||||||
|
self.transitions(),
|
||||||
|
self.project().client_compile_time_info(),
|
||||||
|
self.client_module_options_context(),
|
||||||
|
self.client_resolve_options_context(),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[turbo_tasks::function]
|
||||||
|
pub(super) fn ssr_module_context(self: Vc<Self>) -> Vc<Box<dyn AssetContext>> {
|
||||||
|
Vc::upcast(ModuleAssetContext::new(
|
||||||
|
self.transitions(),
|
||||||
|
self.project().server_compile_time_info(),
|
||||||
|
self.ssr_module_options_context(),
|
||||||
|
self.ssr_resolve_options_context(),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[turbo_tasks::function]
|
||||||
|
pub(super) fn ssr_data_module_context(self: Vc<Self>) -> Vc<Box<dyn AssetContext>> {
|
||||||
|
Vc::upcast(ModuleAssetContext::new(
|
||||||
|
self.transitions(),
|
||||||
|
self.project().server_compile_time_info(),
|
||||||
|
self.ssr_data_module_options_context(),
|
||||||
|
self.ssr_resolve_options_context(),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[turbo_tasks::function]
|
||||||
|
async fn ssr_module_options_context(self: Vc<Self>) -> Result<Vc<ModuleOptionsContext>> {
|
||||||
|
let this = self.await?;
|
||||||
|
Ok(get_server_module_options_context(
|
||||||
|
self.project().project_path(),
|
||||||
|
self.project().execution_context(),
|
||||||
|
Value::new(ServerContextType::Pages {
|
||||||
|
pages_dir: self.pages_dir(),
|
||||||
|
}),
|
||||||
|
this.mode,
|
||||||
|
self.project().next_config(),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[turbo_tasks::function]
|
||||||
|
async fn ssr_data_module_options_context(self: Vc<Self>) -> Result<Vc<ModuleOptionsContext>> {
|
||||||
|
let this = self.await?;
|
||||||
|
Ok(get_server_module_options_context(
|
||||||
|
self.project().project_path(),
|
||||||
|
self.project().execution_context(),
|
||||||
|
Value::new(ServerContextType::PagesData {
|
||||||
|
pages_dir: self.pages_dir(),
|
||||||
|
}),
|
||||||
|
this.mode,
|
||||||
|
self.project().next_config(),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[turbo_tasks::function]
|
||||||
|
async fn ssr_resolve_options_context(self: Vc<Self>) -> Result<Vc<ResolveOptionsContext>> {
|
||||||
|
let this = self.await?;
|
||||||
|
Ok(get_server_resolve_options_context(
|
||||||
|
self.project().project_path(),
|
||||||
|
Value::new(ServerContextType::Pages {
|
||||||
|
pages_dir: self.pages_dir(),
|
||||||
|
}),
|
||||||
|
this.mode,
|
||||||
|
self.project().next_config(),
|
||||||
|
self.project().execution_context(),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[turbo_tasks::function]
|
||||||
|
async fn client_runtime_entries(self: Vc<Self>) -> Result<Vc<EvaluatableAssets>> {
|
||||||
|
let this = self.await?;
|
||||||
|
let client_runtime_entries = get_client_runtime_entries(
|
||||||
|
self.project().project_path(),
|
||||||
|
self.project().env(),
|
||||||
|
Value::new(ClientContextType::Pages {
|
||||||
|
pages_dir: self.pages_dir(),
|
||||||
|
}),
|
||||||
|
this.mode,
|
||||||
|
self.project().next_config(),
|
||||||
|
self.project().execution_context(),
|
||||||
|
);
|
||||||
|
Ok(client_runtime_entries.resolve_entries(self.client_module_context()))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[turbo_tasks::function]
|
||||||
|
async fn ssr_runtime_entries(self: Vc<Self>) -> Result<Vc<EvaluatableAssets>> {
|
||||||
|
let this = self.await?;
|
||||||
|
let ssr_runtime_entries = get_server_runtime_entries(
|
||||||
|
self.project().project_path(),
|
||||||
|
self.project().env(),
|
||||||
|
Value::new(ServerContextType::Pages {
|
||||||
|
pages_dir: self.pages_dir(),
|
||||||
|
}),
|
||||||
|
this.mode,
|
||||||
|
self.project().next_config(),
|
||||||
|
);
|
||||||
|
Ok(ssr_runtime_entries.resolve_entries(self.ssr_module_context()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[turbo_tasks::value]
|
#[turbo_tasks::value]
|
||||||
struct PageHtmlEndpoint {
|
struct PageHtmlEndpoint {
|
||||||
project: Vc<Project>,
|
pages_project: Vc<PagesProject>,
|
||||||
pathname: Vc<String>,
|
pathname: Vc<String>,
|
||||||
original_name: Vc<String>,
|
original_name: Vc<String>,
|
||||||
path: Vc<FileSystemPath>,
|
path: Vc<FileSystemPath>,
|
||||||
|
@ -107,13 +314,13 @@ struct PageHtmlEndpoint {
|
||||||
impl PageHtmlEndpoint {
|
impl PageHtmlEndpoint {
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn new(
|
fn new(
|
||||||
project: Vc<Project>,
|
pages_project: Vc<PagesProject>,
|
||||||
pathname: Vc<String>,
|
pathname: Vc<String>,
|
||||||
original_name: Vc<String>,
|
original_name: Vc<String>,
|
||||||
path: Vc<FileSystemPath>,
|
path: Vc<FileSystemPath>,
|
||||||
) -> Vc<Self> {
|
) -> Vc<Self> {
|
||||||
PageHtmlEndpoint {
|
PageHtmlEndpoint {
|
||||||
project,
|
pages_project,
|
||||||
pathname,
|
pathname,
|
||||||
original_name,
|
original_name,
|
||||||
path,
|
path,
|
||||||
|
@ -132,7 +339,7 @@ impl PageHtmlEndpoint {
|
||||||
let this = self.await?;
|
let this = self.await?;
|
||||||
|
|
||||||
let client_module = create_page_loader_entry_module(
|
let client_module = create_page_loader_entry_module(
|
||||||
this.project.pages_client_module_context(),
|
this.pages_project.client_module_context(),
|
||||||
self.source(),
|
self.source(),
|
||||||
this.pathname,
|
this.pathname,
|
||||||
);
|
);
|
||||||
|
@ -143,14 +350,14 @@ impl PageHtmlEndpoint {
|
||||||
bail!("expected an ECMAScript module asset");
|
bail!("expected an ECMAScript module asset");
|
||||||
};
|
};
|
||||||
|
|
||||||
let client_chunking_context = this.project.client_chunking_context();
|
let client_chunking_context = this.pages_project.project().client_chunking_context();
|
||||||
|
|
||||||
let client_entry_chunk = client_module.as_root_chunk(Vc::upcast(client_chunking_context));
|
let client_entry_chunk = client_module.as_root_chunk(Vc::upcast(client_chunking_context));
|
||||||
|
|
||||||
let client_chunks = client_chunking_context.evaluated_chunk_group(
|
let client_chunks = client_chunking_context.evaluated_chunk_group(
|
||||||
client_entry_chunk,
|
client_entry_chunk,
|
||||||
this.project
|
this.pages_project
|
||||||
.pages_client_runtime_entries()
|
.client_runtime_entries()
|
||||||
.with_entry(Vc::upcast(client_module)),
|
.with_entry(Vc::upcast(client_module)),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -163,8 +370,8 @@ impl PageHtmlEndpoint {
|
||||||
let reference_type = Value::new(ReferenceType::Entry(EntryReferenceSubType::Page));
|
let reference_type = Value::new(ReferenceType::Entry(EntryReferenceSubType::Page));
|
||||||
|
|
||||||
let ssr_module = this
|
let ssr_module = this
|
||||||
.project
|
.pages_project
|
||||||
.pages_ssr_module_context()
|
.ssr_module_context()
|
||||||
.process(self.source(), reference_type.clone());
|
.process(self.source(), reference_type.clone());
|
||||||
|
|
||||||
let Some(ssr_module) =
|
let Some(ssr_module) =
|
||||||
|
@ -176,11 +383,19 @@ impl PageHtmlEndpoint {
|
||||||
let asset_path = get_asset_path_from_pathname(&this.pathname.await?, ".js");
|
let asset_path = get_asset_path_from_pathname(&this.pathname.await?, ".js");
|
||||||
|
|
||||||
let ssr_entry_chunk_path_string = format!("server/pages{asset_path}");
|
let ssr_entry_chunk_path_string = format!("server/pages{asset_path}");
|
||||||
let ssr_entry_chunk_path = this.project.node_root().join(ssr_entry_chunk_path_string);
|
let ssr_entry_chunk_path = this
|
||||||
let ssr_entry_chunk = this.project.ssr_chunking_context().entry_chunk(
|
.pages_project
|
||||||
|
.project()
|
||||||
|
.node_root()
|
||||||
|
.join(ssr_entry_chunk_path_string);
|
||||||
|
let ssr_entry_chunk = this
|
||||||
|
.pages_project
|
||||||
|
.project()
|
||||||
|
.ssr_chunking_context()
|
||||||
|
.entry_chunk(
|
||||||
ssr_entry_chunk_path,
|
ssr_entry_chunk_path,
|
||||||
Vc::upcast(ssr_module),
|
Vc::upcast(ssr_module),
|
||||||
this.project.pages_ssr_runtime_entries(),
|
this.pages_project.ssr_runtime_entries(),
|
||||||
);
|
);
|
||||||
|
|
||||||
Ok(ssr_entry_chunk)
|
Ok(ssr_entry_chunk)
|
||||||
|
@ -195,15 +410,15 @@ impl Endpoint for PageHtmlEndpoint {
|
||||||
let ssr_chunk = self.ssr_chunk();
|
let ssr_chunk = self.ssr_chunk();
|
||||||
let ssr_emit = emit_all_assets(
|
let ssr_emit = emit_all_assets(
|
||||||
Vc::cell(vec![ssr_chunk]),
|
Vc::cell(vec![ssr_chunk]),
|
||||||
this.project.node_root(),
|
this.pages_project.project().node_root(),
|
||||||
this.project.client_root().join("_next".to_string()),
|
this.pages_project.project().client_relative_path(),
|
||||||
this.project.node_root(),
|
this.pages_project.project().node_root(),
|
||||||
);
|
);
|
||||||
let client_emit = emit_all_assets(
|
let client_emit = emit_all_assets(
|
||||||
self.client_chunks(),
|
self.client_chunks(),
|
||||||
this.project.node_root(),
|
this.pages_project.project().node_root(),
|
||||||
this.project.client_root().join("_next".to_string()),
|
this.pages_project.project().client_relative_path(),
|
||||||
this.project.node_root(),
|
this.pages_project.project().node_root(),
|
||||||
);
|
);
|
||||||
|
|
||||||
ssr_emit.await?;
|
ssr_emit.await?;
|
||||||
|
@ -211,7 +426,8 @@ impl Endpoint for PageHtmlEndpoint {
|
||||||
|
|
||||||
Ok(WrittenEndpoint {
|
Ok(WrittenEndpoint {
|
||||||
server_entry_path: this
|
server_entry_path: this
|
||||||
.project
|
.pages_project
|
||||||
|
.project()
|
||||||
.node_root()
|
.node_root()
|
||||||
.await?
|
.await?
|
||||||
.get_path_to(&*ssr_chunk.ident().path().await?)
|
.get_path_to(&*ssr_chunk.ident().path().await?)
|
||||||
|
@ -234,7 +450,7 @@ impl Endpoint for PageHtmlEndpoint {
|
||||||
|
|
||||||
#[turbo_tasks::value]
|
#[turbo_tasks::value]
|
||||||
struct PageDataEndpoint {
|
struct PageDataEndpoint {
|
||||||
project: Vc<Project>,
|
pages_project: Vc<PagesProject>,
|
||||||
pathname: Vc<String>,
|
pathname: Vc<String>,
|
||||||
original_name: Vc<String>,
|
original_name: Vc<String>,
|
||||||
path: Vc<FileSystemPath>,
|
path: Vc<FileSystemPath>,
|
||||||
|
@ -244,13 +460,13 @@ struct PageDataEndpoint {
|
||||||
impl PageDataEndpoint {
|
impl PageDataEndpoint {
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn new(
|
fn new(
|
||||||
project: Vc<Project>,
|
pages_project: Vc<PagesProject>,
|
||||||
pathname: Vc<String>,
|
pathname: Vc<String>,
|
||||||
original_name: Vc<String>,
|
original_name: Vc<String>,
|
||||||
path: Vc<FileSystemPath>,
|
path: Vc<FileSystemPath>,
|
||||||
) -> Vc<Self> {
|
) -> Vc<Self> {
|
||||||
PageDataEndpoint {
|
PageDataEndpoint {
|
||||||
project,
|
pages_project,
|
||||||
pathname,
|
pathname,
|
||||||
original_name,
|
original_name,
|
||||||
path,
|
path,
|
||||||
|
@ -270,8 +486,8 @@ impl PageDataEndpoint {
|
||||||
let reference_type = Value::new(ReferenceType::Entry(EntryReferenceSubType::Page));
|
let reference_type = Value::new(ReferenceType::Entry(EntryReferenceSubType::Page));
|
||||||
|
|
||||||
let ssr_data_module = this
|
let ssr_data_module = this
|
||||||
.project
|
.pages_project
|
||||||
.pages_ssr_data_module_context()
|
.ssr_data_module_context()
|
||||||
.process(self.source(), reference_type.clone());
|
.process(self.source(), reference_type.clone());
|
||||||
|
|
||||||
let Some(ssr_data_module) =
|
let Some(ssr_data_module) =
|
||||||
|
@ -284,13 +500,18 @@ impl PageDataEndpoint {
|
||||||
|
|
||||||
let ssr_data_entry_chunk_path_string = format!("server/pages-data/{asset_path}");
|
let ssr_data_entry_chunk_path_string = format!("server/pages-data/{asset_path}");
|
||||||
let ssr_data_entry_chunk_path = this
|
let ssr_data_entry_chunk_path = this
|
||||||
.project
|
.pages_project
|
||||||
|
.project()
|
||||||
.node_root()
|
.node_root()
|
||||||
.join(ssr_data_entry_chunk_path_string);
|
.join(ssr_data_entry_chunk_path_string);
|
||||||
let ssr_data_entry_chunk = this.project.ssr_data_chunking_context().entry_chunk(
|
let ssr_data_entry_chunk = this
|
||||||
|
.pages_project
|
||||||
|
.project()
|
||||||
|
.ssr_data_chunking_context()
|
||||||
|
.entry_chunk(
|
||||||
ssr_data_entry_chunk_path,
|
ssr_data_entry_chunk_path,
|
||||||
Vc::upcast(ssr_data_module),
|
Vc::upcast(ssr_data_module),
|
||||||
this.project.pages_ssr_runtime_entries(),
|
this.pages_project.ssr_runtime_entries(),
|
||||||
);
|
);
|
||||||
|
|
||||||
Ok(ssr_data_entry_chunk)
|
Ok(ssr_data_entry_chunk)
|
||||||
|
@ -305,15 +526,16 @@ impl Endpoint for PageDataEndpoint {
|
||||||
let ssr_data_chunk = self.ssr_data_chunk();
|
let ssr_data_chunk = self.ssr_data_chunk();
|
||||||
emit_all_assets(
|
emit_all_assets(
|
||||||
Vc::cell(vec![ssr_data_chunk]),
|
Vc::cell(vec![ssr_data_chunk]),
|
||||||
this.project.node_root(),
|
this.pages_project.project().node_root(),
|
||||||
this.project.client_root().join("_next".to_string()),
|
this.pages_project.project().client_relative_path(),
|
||||||
this.project.node_root(),
|
this.pages_project.project().node_root(),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
Ok(WrittenEndpoint {
|
Ok(WrittenEndpoint {
|
||||||
server_entry_path: this
|
server_entry_path: this
|
||||||
.project
|
.pages_project
|
||||||
|
.project()
|
||||||
.node_root()
|
.node_root()
|
||||||
.await?
|
.await?
|
||||||
.get_path_to(&*ssr_data_chunk.ident().path().await?)
|
.get_path_to(&*ssr_data_chunk.ident().path().await?)
|
||||||
|
@ -332,41 +554,105 @@ impl Endpoint for PageDataEndpoint {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::value]
|
#[turbo_tasks::value]
|
||||||
struct ApiEndpoint {
|
struct PageApiEndpoint {
|
||||||
project: Vc<Project>,
|
pages_project: Vc<PagesProject>,
|
||||||
pathname: Vc<String>,
|
pathname: Vc<String>,
|
||||||
original_name: Vc<String>,
|
original_name: Vc<String>,
|
||||||
path: Vc<FileSystemPath>,
|
path: Vc<FileSystemPath>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::value_impl]
|
#[turbo_tasks::value_impl]
|
||||||
impl ApiEndpoint {
|
impl PageApiEndpoint {
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn new(
|
fn new(
|
||||||
project: Vc<Project>,
|
pages_project: Vc<PagesProject>,
|
||||||
pathname: Vc<String>,
|
pathname: Vc<String>,
|
||||||
original_name: Vc<String>,
|
original_name: Vc<String>,
|
||||||
path: Vc<FileSystemPath>,
|
path: Vc<FileSystemPath>,
|
||||||
) -> Vc<Self> {
|
) -> Vc<Self> {
|
||||||
ApiEndpoint {
|
PageApiEndpoint {
|
||||||
project,
|
pages_project,
|
||||||
pathname,
|
pathname,
|
||||||
original_name,
|
original_name,
|
||||||
path,
|
path,
|
||||||
}
|
}
|
||||||
.cell()
|
.cell()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[turbo_tasks::function]
|
||||||
|
fn source(&self) -> Vc<Box<dyn Source>> {
|
||||||
|
Vc::upcast(FileSource::new(self.path))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[turbo_tasks::function]
|
||||||
|
async fn api_chunk(self: Vc<Self>) -> Result<Vc<Box<dyn OutputAsset>>> {
|
||||||
|
let this = self.await?;
|
||||||
|
let reference_type = Value::new(ReferenceType::Entry(EntryReferenceSubType::PagesApi));
|
||||||
|
|
||||||
|
let api_module = this
|
||||||
|
.pages_project
|
||||||
|
.ssr_module_context()
|
||||||
|
.process(self.source(), reference_type.clone());
|
||||||
|
|
||||||
|
let Some(api_module) =
|
||||||
|
Vc::try_resolve_downcast_type::<EcmascriptModuleAsset>(api_module).await?
|
||||||
|
else {
|
||||||
|
bail!("expected an ECMAScript module asset");
|
||||||
|
};
|
||||||
|
|
||||||
|
let asset_path = get_asset_path_from_pathname(&this.pathname.await?, ".js");
|
||||||
|
|
||||||
|
let api_entry_chunk_path_string = format!("server/pages/{asset_path}");
|
||||||
|
let api_entry_chunk_path = this
|
||||||
|
.pages_project
|
||||||
|
.project()
|
||||||
|
.node_root()
|
||||||
|
.join(api_entry_chunk_path_string);
|
||||||
|
let api_entry_chunk = this
|
||||||
|
.pages_project
|
||||||
|
.project()
|
||||||
|
.ssr_chunking_context()
|
||||||
|
.entry_chunk(
|
||||||
|
api_entry_chunk_path,
|
||||||
|
Vc::upcast(api_module),
|
||||||
|
this.pages_project.ssr_runtime_entries(),
|
||||||
|
);
|
||||||
|
|
||||||
|
Ok(api_entry_chunk)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::value_impl]
|
#[turbo_tasks::value_impl]
|
||||||
impl Endpoint for ApiEndpoint {
|
impl Endpoint for PageApiEndpoint {
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn write_to_disk(&self) -> Vc<WrittenEndpoint> {
|
async fn write_to_disk(self: Vc<Self>) -> Result<Vc<WrittenEndpoint>> {
|
||||||
todo!()
|
let this = self.await?;
|
||||||
|
let api_chunk = self.api_chunk();
|
||||||
|
emit_all_assets(
|
||||||
|
Vc::cell(vec![api_chunk]),
|
||||||
|
this.pages_project.project().node_root(),
|
||||||
|
this.pages_project.project().client_relative_path(),
|
||||||
|
this.pages_project.project().node_root(),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
Ok(WrittenEndpoint {
|
||||||
|
server_entry_path: this
|
||||||
|
.pages_project
|
||||||
|
.project()
|
||||||
|
.node_root()
|
||||||
|
.await?
|
||||||
|
.get_path_to(&*api_chunk.ident().path().await?)
|
||||||
|
.context("API chunk entry path must be inside the node root")?
|
||||||
|
.to_string(),
|
||||||
|
server_paths: vec![],
|
||||||
|
}
|
||||||
|
.cell())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn changed(&self) -> Vc<Completion> {
|
fn changed(self: Vc<Self>) -> Vc<Completion> {
|
||||||
todo!()
|
let api_chunk = self.api_chunk();
|
||||||
|
any_content_changed(Vc::upcast(api_chunk))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,27 +3,16 @@ use std::path::MAIN_SEPARATOR;
|
||||||
use anyhow::{Context, Result};
|
use anyhow::{Context, Result};
|
||||||
use indexmap::{map::Entry, IndexMap};
|
use indexmap::{map::Entry, IndexMap};
|
||||||
use next_core::{
|
use next_core::{
|
||||||
app_structure::{find_app_dir, get_entrypoints},
|
app_structure::find_app_dir,
|
||||||
mode::NextMode,
|
mode::NextMode,
|
||||||
next_client::{
|
next_client::{get_client_chunking_context, get_client_compile_time_info},
|
||||||
get_client_chunking_context, get_client_compile_time_info,
|
|
||||||
get_client_module_options_context, get_client_resolve_options_context,
|
|
||||||
get_client_runtime_entries, ClientContextType,
|
|
||||||
},
|
|
||||||
next_config::NextConfig,
|
next_config::NextConfig,
|
||||||
next_dynamic::NextDynamicTransition,
|
next_server::{get_server_chunking_context, get_server_compile_time_info},
|
||||||
next_server::{
|
|
||||||
get_server_chunking_context, get_server_compile_time_info,
|
|
||||||
get_server_module_options_context, get_server_resolve_options_context,
|
|
||||||
get_server_runtime_entries, ServerContextType,
|
|
||||||
},
|
|
||||||
pages_structure::{find_pages_structure, PagesStructure},
|
|
||||||
util::NextSourceConfig,
|
util::NextSourceConfig,
|
||||||
};
|
};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use turbo_tasks::{
|
use turbo_tasks::{
|
||||||
debug::ValueDebugFormat, trace::TraceRawVcs, unit, TaskInput, TransientValue, TryJoinIterExt,
|
debug::ValueDebugFormat, trace::TraceRawVcs, unit, TaskInput, TransientValue, Vc,
|
||||||
Value, Vc,
|
|
||||||
};
|
};
|
||||||
use turbopack_binding::{
|
use turbopack_binding::{
|
||||||
turbo::{
|
turbo::{
|
||||||
|
@ -33,29 +22,21 @@ use turbopack_binding::{
|
||||||
turbopack::{
|
turbopack::{
|
||||||
build::BuildChunkingContext,
|
build::BuildChunkingContext,
|
||||||
core::{
|
core::{
|
||||||
chunk::{ChunkingContext, EvaluatableAssets},
|
chunk::ChunkingContext, compile_time_info::CompileTimeInfo, environment::ServerAddr,
|
||||||
compile_time_info::CompileTimeInfo,
|
|
||||||
context::AssetContext,
|
|
||||||
environment::ServerAddr,
|
|
||||||
PROJECT_FILESYSTEM_NAME,
|
PROJECT_FILESYSTEM_NAME,
|
||||||
},
|
},
|
||||||
dev::DevChunkingContext,
|
dev::DevChunkingContext,
|
||||||
ecmascript::chunk::EcmascriptChunkingContext,
|
ecmascript::chunk::EcmascriptChunkingContext,
|
||||||
env::dotenv::load_env,
|
env::dotenv::load_env,
|
||||||
node::execution_context::ExecutionContext,
|
node::execution_context::ExecutionContext,
|
||||||
turbopack::{
|
turbopack::evaluate_context::node_build_environment,
|
||||||
evaluate_context::node_build_environment,
|
|
||||||
module_options::ModuleOptionsContext,
|
|
||||||
resolve_options_context::ResolveOptionsContext,
|
|
||||||
transition::{ContextTransition, TransitionsByName},
|
|
||||||
ModuleAssetContext,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
app::app_entry_point_to_route,
|
app::{AppProject, OptionAppProject},
|
||||||
pages::get_pages_routes,
|
entrypoints::Entrypoints,
|
||||||
|
pages::PagesProject,
|
||||||
route::{Endpoint, Route},
|
route::{Endpoint, Route},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -85,12 +66,6 @@ pub struct Middleware {
|
||||||
pub config: NextSourceConfig,
|
pub config: NextSourceConfig,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::value]
|
|
||||||
pub struct Entrypoints {
|
|
||||||
pub routes: IndexMap<String, Route>,
|
|
||||||
pub middleware: Option<Middleware>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[turbo_tasks::value]
|
#[turbo_tasks::value]
|
||||||
pub struct Project {
|
pub struct Project {
|
||||||
/// A root path from which all files must be nested under. Trying to access
|
/// A root path from which all files must be nested under. Trying to access
|
||||||
|
@ -129,6 +104,24 @@ impl Project {
|
||||||
.cell())
|
.cell())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[turbo_tasks::function]
|
||||||
|
async fn app_project(self: Vc<Self>) -> Result<Vc<OptionAppProject>> {
|
||||||
|
let this = self.await?;
|
||||||
|
let app_dir = find_app_dir(self.project_path()).await?;
|
||||||
|
|
||||||
|
Ok(Vc::cell(if let Some(app_dir) = &*app_dir {
|
||||||
|
Some(AppProject::new(self, *app_dir, this.mode))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[turbo_tasks::function]
|
||||||
|
async fn pages_project(self: Vc<Self>) -> Result<Vc<PagesProject>> {
|
||||||
|
let this = self.await?;
|
||||||
|
Ok(PagesProject::new(self, this.mode))
|
||||||
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
async fn project_fs(self: Vc<Self>) -> Result<Vc<Box<dyn FileSystem>>> {
|
async fn project_fs(self: Vc<Self>) -> Result<Vc<Box<dyn FileSystem>>> {
|
||||||
let this = self.await?;
|
let this = self.await?;
|
||||||
|
@ -172,7 +165,12 @@ impl Project {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
async fn project_path(self: Vc<Self>) -> Result<Vc<FileSystemPath>> {
|
pub(super) fn client_relative_path(self: Vc<Self>) -> Vc<FileSystemPath> {
|
||||||
|
self.client_root().join("_next".to_string())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[turbo_tasks::function]
|
||||||
|
pub(super) async fn project_path(self: Vc<Self>) -> Result<Vc<FileSystemPath>> {
|
||||||
let this = self.await?;
|
let this = self.await?;
|
||||||
let root = self.project_root_path();
|
let root = self.project_root_path();
|
||||||
let project_relative = this.project_path.strip_prefix(&this.root_path).unwrap();
|
let project_relative = this.project_path.strip_prefix(&this.root_path).unwrap();
|
||||||
|
@ -184,29 +182,17 @@ impl Project {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
async fn pages_structure(self: Vc<Self>) -> Result<Vc<PagesStructure>> {
|
pub(super) fn env(self: Vc<Self>) -> Vc<Box<dyn ProcessEnv>> {
|
||||||
let this: turbo_tasks::ReadRef<Project> = self.await?;
|
|
||||||
let next_router_fs = Vc::upcast::<Box<dyn FileSystem>>(VirtualFileSystem::new());
|
|
||||||
let next_router_root = next_router_fs.root();
|
|
||||||
Ok(find_pages_structure(
|
|
||||||
self.project_path(),
|
|
||||||
next_router_root,
|
|
||||||
this.next_config.page_extensions(),
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
|
||||||
fn env(self: Vc<Self>) -> Vc<Box<dyn ProcessEnv>> {
|
|
||||||
load_env(self.project_path())
|
load_env(self.project_path())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
async fn next_config(self: Vc<Self>) -> Result<Vc<NextConfig>> {
|
pub(super) async fn next_config(self: Vc<Self>) -> Result<Vc<NextConfig>> {
|
||||||
Ok(self.await?.next_config)
|
Ok(self.await?.next_config)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
fn execution_context(self: Vc<Self>) -> Vc<ExecutionContext> {
|
pub(super) fn execution_context(self: Vc<Self>) -> Vc<ExecutionContext> {
|
||||||
let node_root = self.node_root();
|
let node_root = self.node_root();
|
||||||
|
|
||||||
let node_execution_chunking_context = Vc::upcast(
|
let node_execution_chunking_context = Vc::upcast(
|
||||||
|
@ -228,16 +214,12 @@ impl Project {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
async fn client_compile_time_info(self: Vc<Self>) -> Result<Vc<CompileTimeInfo>> {
|
pub(super) fn client_compile_time_info(&self) -> Vc<CompileTimeInfo> {
|
||||||
let this = self.await?;
|
get_client_compile_time_info(self.mode, self.browserslist_query.clone())
|
||||||
Ok(get_client_compile_time_info(
|
|
||||||
this.mode,
|
|
||||||
this.browserslist_query.clone(),
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
async fn server_compile_time_info(self: Vc<Self>) -> Result<Vc<CompileTimeInfo>> {
|
pub(super) async fn server_compile_time_info(self: Vc<Self>) -> Result<Vc<CompileTimeInfo>> {
|
||||||
let this = self.await?;
|
let this = self.await?;
|
||||||
Ok(get_server_compile_time_info(
|
Ok(get_server_compile_time_info(
|
||||||
this.mode,
|
this.mode,
|
||||||
|
@ -247,178 +229,6 @@ impl Project {
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
|
||||||
async fn pages_dir(self: Vc<Self>) -> Result<Vc<FileSystemPath>> {
|
|
||||||
Ok(if let Some(pages) = self.pages_structure().await?.pages {
|
|
||||||
pages.project_path()
|
|
||||||
} else {
|
|
||||||
self.project_path().join("pages".to_string())
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
|
||||||
fn pages_transitions(self: Vc<Self>) -> Vc<TransitionsByName> {
|
|
||||||
Vc::cell(
|
|
||||||
[(
|
|
||||||
"next-dynamic".to_string(),
|
|
||||||
Vc::upcast(NextDynamicTransition::new(self.pages_client_transition())),
|
|
||||||
)]
|
|
||||||
.into_iter()
|
|
||||||
.collect(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
|
||||||
fn pages_client_transition(self: Vc<Self>) -> Vc<ContextTransition> {
|
|
||||||
ContextTransition::new(
|
|
||||||
self.client_compile_time_info(),
|
|
||||||
self.pages_client_module_options_context(),
|
|
||||||
self.pages_client_resolve_options_context(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
|
||||||
async fn pages_client_module_options_context(
|
|
||||||
self: Vc<Self>,
|
|
||||||
) -> Result<Vc<ModuleOptionsContext>> {
|
|
||||||
let this = self.await?;
|
|
||||||
Ok(get_client_module_options_context(
|
|
||||||
self.project_path(),
|
|
||||||
self.execution_context(),
|
|
||||||
self.client_compile_time_info().environment(),
|
|
||||||
Value::new(ClientContextType::Pages {
|
|
||||||
pages_dir: self.pages_dir(),
|
|
||||||
}),
|
|
||||||
this.mode,
|
|
||||||
self.next_config(),
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
|
||||||
async fn pages_client_resolve_options_context(
|
|
||||||
self: Vc<Self>,
|
|
||||||
) -> Result<Vc<ResolveOptionsContext>> {
|
|
||||||
let this = self.await?;
|
|
||||||
Ok(get_client_resolve_options_context(
|
|
||||||
self.project_path(),
|
|
||||||
Value::new(ClientContextType::Pages {
|
|
||||||
pages_dir: self.pages_dir(),
|
|
||||||
}),
|
|
||||||
this.mode,
|
|
||||||
self.next_config(),
|
|
||||||
self.execution_context(),
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
|
||||||
pub(super) fn pages_client_module_context(self: Vc<Self>) -> Vc<Box<dyn AssetContext>> {
|
|
||||||
Vc::upcast(ModuleAssetContext::new(
|
|
||||||
self.pages_transitions(),
|
|
||||||
self.client_compile_time_info(),
|
|
||||||
self.pages_client_module_options_context(),
|
|
||||||
self.pages_client_resolve_options_context(),
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
|
||||||
pub(super) fn pages_ssr_module_context(self: Vc<Self>) -> Vc<Box<dyn AssetContext>> {
|
|
||||||
Vc::upcast(ModuleAssetContext::new(
|
|
||||||
self.pages_transitions(),
|
|
||||||
self.server_compile_time_info(),
|
|
||||||
self.pages_ssr_module_options_context(),
|
|
||||||
self.pages_ssr_resolve_options_context(),
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
|
||||||
pub(super) fn pages_ssr_data_module_context(self: Vc<Self>) -> Vc<Box<dyn AssetContext>> {
|
|
||||||
Vc::upcast(ModuleAssetContext::new(
|
|
||||||
self.pages_transitions(),
|
|
||||||
self.server_compile_time_info(),
|
|
||||||
self.pages_ssr_data_module_options_context(),
|
|
||||||
self.pages_ssr_resolve_options_context(),
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
|
||||||
async fn pages_ssr_module_options_context(self: Vc<Self>) -> Result<Vc<ModuleOptionsContext>> {
|
|
||||||
let this = self.await?;
|
|
||||||
Ok(get_server_module_options_context(
|
|
||||||
self.project_path(),
|
|
||||||
self.execution_context(),
|
|
||||||
Value::new(ServerContextType::Pages {
|
|
||||||
pages_dir: self.pages_dir(),
|
|
||||||
}),
|
|
||||||
this.mode,
|
|
||||||
self.next_config(),
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
|
||||||
async fn pages_ssr_data_module_options_context(
|
|
||||||
self: Vc<Self>,
|
|
||||||
) -> Result<Vc<ModuleOptionsContext>> {
|
|
||||||
let this = self.await?;
|
|
||||||
Ok(get_server_module_options_context(
|
|
||||||
self.project_path(),
|
|
||||||
self.execution_context(),
|
|
||||||
Value::new(ServerContextType::PagesData {
|
|
||||||
pages_dir: self.pages_dir(),
|
|
||||||
}),
|
|
||||||
this.mode,
|
|
||||||
self.next_config(),
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
|
||||||
async fn pages_ssr_resolve_options_context(
|
|
||||||
self: Vc<Self>,
|
|
||||||
) -> Result<Vc<ResolveOptionsContext>> {
|
|
||||||
let this = self.await?;
|
|
||||||
Ok(get_server_resolve_options_context(
|
|
||||||
self.project_path(),
|
|
||||||
Value::new(ServerContextType::Pages {
|
|
||||||
pages_dir: self.pages_dir(),
|
|
||||||
}),
|
|
||||||
this.mode,
|
|
||||||
self.next_config(),
|
|
||||||
self.execution_context(),
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
|
||||||
pub(super) async fn pages_client_runtime_entries(
|
|
||||||
self: Vc<Self>,
|
|
||||||
) -> Result<Vc<EvaluatableAssets>> {
|
|
||||||
let this = self.await?;
|
|
||||||
let client_runtime_entries = get_client_runtime_entries(
|
|
||||||
self.project_path(),
|
|
||||||
self.env(),
|
|
||||||
Value::new(ClientContextType::Pages {
|
|
||||||
pages_dir: self.pages_dir(),
|
|
||||||
}),
|
|
||||||
this.mode,
|
|
||||||
self.next_config(),
|
|
||||||
self.execution_context(),
|
|
||||||
);
|
|
||||||
Ok(client_runtime_entries.resolve_entries(self.pages_client_module_context()))
|
|
||||||
}
|
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
|
||||||
pub(super) async fn pages_ssr_runtime_entries(self: Vc<Self>) -> Result<Vc<EvaluatableAssets>> {
|
|
||||||
let this = self.await?;
|
|
||||||
let ssr_runtime_entries = get_server_runtime_entries(
|
|
||||||
self.project_path(),
|
|
||||||
self.env(),
|
|
||||||
Value::new(ServerContextType::Pages {
|
|
||||||
pages_dir: self.pages_dir(),
|
|
||||||
}),
|
|
||||||
this.mode,
|
|
||||||
self.next_config(),
|
|
||||||
);
|
|
||||||
Ok(ssr_runtime_entries.resolve_entries(self.pages_ssr_module_context()))
|
|
||||||
}
|
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
pub(super) async fn client_chunking_context(
|
pub(super) async fn client_chunking_context(
|
||||||
self: Vc<Self>,
|
self: Vc<Self>,
|
||||||
|
@ -474,25 +284,16 @@ impl Project {
|
||||||
/// provided page_extensions).
|
/// provided page_extensions).
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
pub async fn entrypoints(self: Vc<Self>) -> Result<Vc<Entrypoints>> {
|
pub async fn entrypoints(self: Vc<Self>) -> Result<Vc<Entrypoints>> {
|
||||||
let this = self.await?;
|
|
||||||
let mut routes = IndexMap::new();
|
let mut routes = IndexMap::new();
|
||||||
if let Some(app_dir) = *find_app_dir(self.project_path()).await? {
|
let app_project = self.app_project();
|
||||||
let app_entrypoints = get_entrypoints(app_dir, this.next_config.page_extensions());
|
let pages_project = self.pages_project();
|
||||||
routes.extend(
|
|
||||||
app_entrypoints
|
if let Some(app_project) = &*app_project.await? {
|
||||||
.await?
|
let app_routes = app_project.routes();
|
||||||
.iter()
|
routes.extend(app_routes.await?.iter().map(|(k, v)| (k.clone(), *v)));
|
||||||
.map(|(pathname, app_entrypoint)| async {
|
|
||||||
Ok((
|
|
||||||
pathname.clone(),
|
|
||||||
*app_entry_point_to_route(*app_entrypoint).await?,
|
|
||||||
))
|
|
||||||
})
|
|
||||||
.try_join()
|
|
||||||
.await?,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
for (pathname, page_route) in get_pages_routes(self, self.pages_structure()).await?.iter() {
|
|
||||||
|
for (pathname, page_route) in pages_project.routes().await?.iter() {
|
||||||
match routes.entry(pathname.clone()) {
|
match routes.entry(pathname.clone()) {
|
||||||
Entry::Occupied(mut entry) => {
|
Entry::Occupied(mut entry) => {
|
||||||
*entry.get_mut() = Route::Conflict;
|
*entry.get_mut() = Route::Conflict;
|
||||||
|
@ -502,6 +303,7 @@ impl Project {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO middleware
|
// TODO middleware
|
||||||
Ok(Entrypoints {
|
Ok(Entrypoints {
|
||||||
routes,
|
routes,
|
||||||
|
|
|
@ -8,7 +8,6 @@ use turbopack_binding::turbo::{
|
||||||
};
|
};
|
||||||
|
|
||||||
pub mod build_options;
|
pub mod build_options;
|
||||||
pub mod manifests;
|
|
||||||
pub(crate) mod next_app;
|
pub(crate) mod next_app;
|
||||||
pub(crate) mod next_build;
|
pub(crate) mod next_build;
|
||||||
pub(crate) mod next_pages;
|
pub(crate) mod next_pages;
|
||||||
|
|
|
@ -1,78 +1,44 @@
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use anyhow::{Context, Result};
|
use anyhow::Result;
|
||||||
use indexmap::IndexMap;
|
|
||||||
use indoc::formatdoc;
|
|
||||||
use next_core::{
|
use next_core::{
|
||||||
app_structure::{find_app_dir_if_enabled, get_entrypoints, get_global_metadata, Entrypoint},
|
app_structure::{find_app_dir_if_enabled, get_entrypoints, get_global_metadata, Entrypoint},
|
||||||
mode::NextMode,
|
mode::NextMode,
|
||||||
|
next_app::{
|
||||||
|
get_app_client_shared_chunks, get_app_page_entry, get_app_route_entry,
|
||||||
|
get_app_route_favicon_entry, AppEntry, ClientReferencesChunks,
|
||||||
|
},
|
||||||
next_client::{
|
next_client::{
|
||||||
get_client_module_options_context, get_client_resolve_options_context,
|
get_client_module_options_context, get_client_resolve_options_context,
|
||||||
get_client_runtime_entries, ClientContextType,
|
get_client_runtime_entries, ClientContextType,
|
||||||
},
|
},
|
||||||
next_client_reference::{
|
next_client_reference::{ClientReferenceGraph, NextEcmascriptClientReferenceTransition},
|
||||||
ClientReference, ClientReferenceType, NextEcmascriptClientReferenceTransition,
|
|
||||||
},
|
|
||||||
next_config::NextConfig,
|
next_config::NextConfig,
|
||||||
next_dynamic::NextDynamicTransition,
|
next_dynamic::NextDynamicTransition,
|
||||||
|
next_manifests::{AppBuildManifest, AppPathsManifest, BuildManifest, ClientReferenceManifest},
|
||||||
next_server::{
|
next_server::{
|
||||||
get_server_module_options_context, get_server_resolve_options_context,
|
get_server_module_options_context, get_server_resolve_options_context,
|
||||||
get_server_runtime_entries, ServerContextType,
|
get_server_runtime_entries, ServerContextType,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use turbo_tasks::{TryJoinIterExt, Value, ValueToString, Vc};
|
use turbo_tasks::{TryJoinIterExt, Value, Vc};
|
||||||
use turbopack_binding::{
|
use turbopack_binding::{
|
||||||
turbo::{
|
turbo::{
|
||||||
tasks_env::{CustomProcessEnv, ProcessEnv},
|
tasks_env::{CustomProcessEnv, ProcessEnv},
|
||||||
tasks_fs::{File, FileSystemPath},
|
tasks_fs::FileSystemPath,
|
||||||
},
|
},
|
||||||
turbopack::{
|
turbopack::{
|
||||||
build::BuildChunkingContext,
|
build::BuildChunkingContext,
|
||||||
core::{
|
core::{
|
||||||
asset::{Asset, AssetContent},
|
asset::Asset, chunk::EvaluatableAssets, compile_time_info::CompileTimeInfo,
|
||||||
chunk::{
|
file_source::FileSource, output::OutputAsset,
|
||||||
availability_info::AvailabilityInfo, ChunkingContext, EvaluatableAssets,
|
|
||||||
ModuleId as TurbopackModuleId,
|
|
||||||
},
|
|
||||||
compile_time_info::CompileTimeInfo,
|
|
||||||
file_source::FileSource,
|
|
||||||
output::{OutputAsset, OutputAssets},
|
|
||||||
raw_output::RawOutput,
|
|
||||||
virtual_source::VirtualSource,
|
|
||||||
},
|
|
||||||
ecmascript::{
|
|
||||||
chunk::{
|
|
||||||
EcmascriptChunk, EcmascriptChunkItemExt, EcmascriptChunkPlaceable,
|
|
||||||
EcmascriptChunkingContext,
|
|
||||||
},
|
|
||||||
utils::StringifyJs,
|
|
||||||
},
|
},
|
||||||
|
ecmascript::chunk::EcmascriptChunkingContext,
|
||||||
node::execution_context::ExecutionContext,
|
node::execution_context::ExecutionContext,
|
||||||
turbopack::{transition::ContextTransition, ModuleAssetContext},
|
turbopack::{transition::ContextTransition, ModuleAssetContext},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{
|
|
||||||
app_client_reference::ClientReferenceChunks, app_page_entry::get_app_page_entry,
|
|
||||||
app_route_entry::get_app_route_entry, app_route_favicon_entry::get_app_route_favicon_entry,
|
|
||||||
};
|
|
||||||
use crate::manifests::{
|
|
||||||
AppBuildManifest, AppPathsManifest, BuildManifest, ClientReferenceManifest, ManifestNode,
|
|
||||||
ManifestNodeEntry, ModuleId,
|
|
||||||
};
|
|
||||||
|
|
||||||
/// The entry module asset for a Next.js app route or page.
|
|
||||||
#[turbo_tasks::value(shared)]
|
|
||||||
pub struct AppEntry {
|
|
||||||
/// The pathname of the route or page.
|
|
||||||
pub pathname: String,
|
|
||||||
/// The original Next.js name of the route or page. This is used instead of
|
|
||||||
/// the pathname to refer to this entry.
|
|
||||||
pub original_name: String,
|
|
||||||
/// The RSC module asset for the route or page.
|
|
||||||
pub rsc_entry: Vc<Box<dyn EcmascriptChunkPlaceable>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[turbo_tasks::value]
|
#[turbo_tasks::value]
|
||||||
pub struct AppEntries {
|
pub struct AppEntries {
|
||||||
/// All app entries.
|
/// All app entries.
|
||||||
|
@ -223,19 +189,19 @@ pub async fn get_app_entries(
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(pathname, entrypoint)| async move {
|
.map(|(pathname, entrypoint)| async move {
|
||||||
Ok(match entrypoint {
|
Ok(match entrypoint {
|
||||||
Entrypoint::AppPage { loader_tree } => {
|
Entrypoint::AppPage { loader_tree } => get_app_page_entry(
|
||||||
get_app_page_entry(rsc_context, *loader_tree, app_dir, pathname, project_root)
|
rsc_context,
|
||||||
.await?
|
*loader_tree,
|
||||||
}
|
app_dir,
|
||||||
Entrypoint::AppRoute { path } => {
|
pathname.clone(),
|
||||||
get_app_route_entry(
|
project_root,
|
||||||
|
),
|
||||||
|
Entrypoint::AppRoute { path } => get_app_route_entry(
|
||||||
rsc_context,
|
rsc_context,
|
||||||
Vc::upcast(FileSource::new(*path)),
|
Vc::upcast(FileSource::new(*path)),
|
||||||
pathname,
|
pathname.clone(),
|
||||||
project_root,
|
project_root,
|
||||||
)
|
),
|
||||||
.await?
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.try_join()
|
.try_join()
|
||||||
|
@ -245,7 +211,11 @@ pub async fn get_app_entries(
|
||||||
let global_metadata = global_metadata.await?;
|
let global_metadata = global_metadata.await?;
|
||||||
|
|
||||||
if let Some(favicon) = global_metadata.favicon {
|
if let Some(favicon) = global_metadata.favicon {
|
||||||
entries.push(get_app_route_favicon_entry(rsc_context, favicon, project_root).await?);
|
entries.push(get_app_route_favicon_entry(
|
||||||
|
rsc_context,
|
||||||
|
favicon,
|
||||||
|
project_root,
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
let client_context = ModuleAssetContext::new(
|
let client_context = ModuleAssetContext::new(
|
||||||
|
@ -276,20 +246,20 @@ pub async fn get_app_entries(
|
||||||
/// manifests.
|
/// manifests.
|
||||||
pub async fn compute_app_entries_chunks(
|
pub async fn compute_app_entries_chunks(
|
||||||
app_entries: &AppEntries,
|
app_entries: &AppEntries,
|
||||||
app_client_references_by_entry: &IndexMap<Vc<Box<dyn Asset>>, Vec<ClientReference>>,
|
app_client_reference_graph: Vc<ClientReferenceGraph>,
|
||||||
app_client_references_chunks: &IndexMap<ClientReferenceType, ClientReferenceChunks>,
|
app_client_references_chunks: Vc<ClientReferencesChunks>,
|
||||||
rsc_chunking_context: Vc<BuildChunkingContext>,
|
rsc_chunking_context: Vc<BuildChunkingContext>,
|
||||||
client_chunking_context: Vc<Box<dyn EcmascriptChunkingContext>>,
|
client_chunking_context: Vc<Box<dyn EcmascriptChunkingContext>>,
|
||||||
ssr_chunking_context: Vc<Box<dyn EcmascriptChunkingContext>>,
|
ssr_chunking_context: Vc<Box<dyn EcmascriptChunkingContext>>,
|
||||||
node_root: Vc<FileSystemPath>,
|
node_root: Vc<FileSystemPath>,
|
||||||
client_relative_path: &FileSystemPath,
|
client_relative_path: Vc<FileSystemPath>,
|
||||||
app_paths_manifest_dir_path: &FileSystemPath,
|
app_paths_manifest_dir_path: &FileSystemPath,
|
||||||
app_build_manifest: &mut AppBuildManifest,
|
app_build_manifest: &mut AppBuildManifest,
|
||||||
build_manifest: &mut BuildManifest,
|
build_manifest: &mut BuildManifest,
|
||||||
app_paths_manifest: &mut AppPathsManifest,
|
app_paths_manifest: &mut AppPathsManifest,
|
||||||
all_chunks: &mut Vec<Vc<Box<dyn OutputAsset>>>,
|
all_chunks: &mut Vec<Vc<Box<dyn OutputAsset>>>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let node_root_ref = node_root.await?;
|
let client_relative_path_ref = client_relative_path.await?;
|
||||||
|
|
||||||
let app_client_shared_chunks =
|
let app_client_shared_chunks =
|
||||||
get_app_client_shared_chunks(app_entries.client_runtime_entries, client_chunking_context);
|
get_app_client_shared_chunks(app_entries.client_runtime_entries, client_chunking_context);
|
||||||
|
@ -300,19 +270,21 @@ pub async fn compute_app_entries_chunks(
|
||||||
|
|
||||||
let chunk_path = chunk.ident().path().await?;
|
let chunk_path = chunk.ident().path().await?;
|
||||||
if chunk_path.extension_ref() == Some("js") {
|
if chunk_path.extension_ref() == Some("js") {
|
||||||
if let Some(chunk_path) = client_relative_path.get_path_to(&chunk_path) {
|
if let Some(chunk_path) = client_relative_path.await?.get_path_to(&chunk_path) {
|
||||||
app_shared_client_chunks_paths.push(chunk_path.to_string());
|
app_shared_client_chunks_paths.push(chunk_path.to_string());
|
||||||
build_manifest.root_main_files.push(chunk_path.to_string());
|
build_manifest.root_main_files.push(chunk_path.to_string());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let app_client_references_chunks_ref = app_client_references_chunks.await?;
|
||||||
|
|
||||||
for app_entry in app_entries.entries.iter().copied() {
|
for app_entry in app_entries.entries.iter().copied() {
|
||||||
let app_entry = app_entry.await?;
|
let app_entry = app_entry.await?;
|
||||||
|
|
||||||
let app_entry_client_references = app_client_references_by_entry
|
let app_entry_client_references = app_client_reference_graph
|
||||||
.get(&Vc::upcast(app_entry.rsc_entry))
|
.entry(Vc::upcast(app_entry.rsc_entry))
|
||||||
.expect("app entry should have a corresponding client references list");
|
.await?;
|
||||||
|
|
||||||
let rsc_chunk = rsc_chunking_context.entry_chunk(
|
let rsc_chunk = rsc_chunking_context.entry_chunk(
|
||||||
node_root.join(format!(
|
node_root.join(format!(
|
||||||
|
@ -325,10 +297,11 @@ pub async fn compute_app_entries_chunks(
|
||||||
all_chunks.push(rsc_chunk);
|
all_chunks.push(rsc_chunk);
|
||||||
|
|
||||||
let mut app_entry_client_chunks = vec![];
|
let mut app_entry_client_chunks = vec![];
|
||||||
|
// TODO(alexkirsz) In which manifest should this go?
|
||||||
let mut app_entry_ssr_chunks = vec![];
|
let mut app_entry_ssr_chunks = vec![];
|
||||||
|
|
||||||
for client_reference in app_entry_client_references {
|
for client_reference in app_entry_client_references.iter() {
|
||||||
let client_reference_chunks = app_client_references_chunks
|
let client_reference_chunks = app_client_references_chunks_ref
|
||||||
.get(client_reference.ty())
|
.get(client_reference.ty())
|
||||||
.expect("client reference should have corresponding chunks");
|
.expect("client reference should have corresponding chunks");
|
||||||
app_entry_client_chunks
|
app_entry_client_chunks
|
||||||
|
@ -344,7 +317,7 @@ pub async fn compute_app_entries_chunks(
|
||||||
let mut app_entry_client_chunks_paths: Vec<_> = app_entry_client_chunks_paths
|
let mut app_entry_client_chunks_paths: Vec<_> = app_entry_client_chunks_paths
|
||||||
.iter()
|
.iter()
|
||||||
.map(|path| {
|
.map(|path| {
|
||||||
client_relative_path
|
client_relative_path_ref
|
||||||
.get_path_to(path)
|
.get_path_to(path)
|
||||||
.expect("asset path should be inside client root")
|
.expect("asset path should be inside client root")
|
||||||
.to_string()
|
.to_string()
|
||||||
|
@ -365,232 +338,18 @@ pub async fn compute_app_entries_chunks(
|
||||||
.to_string(),
|
.to_string(),
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut entry_manifest: ClientReferenceManifest = Default::default();
|
let entry_manifest = ClientReferenceManifest::build_output(
|
||||||
|
node_root,
|
||||||
for app_client_reference in app_entry_client_references {
|
client_relative_path,
|
||||||
let app_client_reference_ty = app_client_reference.ty();
|
app_entry.original_name.clone(),
|
||||||
|
app_client_reference_graph.entry(Vc::upcast(app_entry.rsc_entry)),
|
||||||
let app_client_reference_chunks = app_client_references_chunks
|
app_client_references_chunks,
|
||||||
.get(app_client_reference.ty())
|
client_chunking_context,
|
||||||
.context("client reference chunks not found")?;
|
ssr_chunking_context,
|
||||||
|
|
||||||
let client_reference_chunks = app_client_references_chunks
|
|
||||||
.get(app_client_reference_ty)
|
|
||||||
.context("client reference chunks not found")?;
|
|
||||||
let client_chunks = &client_reference_chunks.client_chunks.await?;
|
|
||||||
|
|
||||||
let client_chunks_paths = client_chunks
|
|
||||||
.iter()
|
|
||||||
.map(|chunk| chunk.ident().path())
|
|
||||||
.try_join()
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
if let Some(server_component) = app_client_reference.server_component() {
|
|
||||||
let server_component_name = server_component
|
|
||||||
.server_path()
|
|
||||||
.with_extension("".to_string())
|
|
||||||
.to_string()
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
let entry_css_files = entry_manifest
|
|
||||||
.entry_css_files
|
|
||||||
.entry(server_component_name.clone_value())
|
|
||||||
.or_insert_with(Default::default);
|
|
||||||
|
|
||||||
match app_client_reference_ty {
|
|
||||||
ClientReferenceType::CssClientReference(_) => {
|
|
||||||
entry_css_files.extend(
|
|
||||||
client_chunks_paths
|
|
||||||
.iter()
|
|
||||||
.filter_map(|chunk_path| {
|
|
||||||
client_relative_path.get_path_to(chunk_path)
|
|
||||||
})
|
|
||||||
.map(ToString::to_string),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
ClientReferenceType::EcmascriptClientReference(_) => {
|
|
||||||
entry_css_files.extend(
|
|
||||||
client_chunks_paths
|
|
||||||
.iter()
|
|
||||||
.filter_map(|chunk_path| {
|
|
||||||
if chunk_path.extension_ref() == Some("css") {
|
|
||||||
client_relative_path.get_path_to(chunk_path)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.map(ToString::to_string),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
match app_client_reference_ty {
|
|
||||||
ClientReferenceType::CssClientReference(_) => {}
|
|
||||||
|
|
||||||
ClientReferenceType::EcmascriptClientReference(ecmascript_client_reference) => {
|
|
||||||
let client_chunks = &app_client_reference_chunks.client_chunks.await?;
|
|
||||||
let ssr_chunks = &app_client_reference_chunks.ssr_chunks.await?;
|
|
||||||
|
|
||||||
let ecmascript_client_reference = ecmascript_client_reference.await?;
|
|
||||||
|
|
||||||
let client_module_id = ecmascript_client_reference
|
|
||||||
.client_module
|
|
||||||
.as_chunk_item(client_chunking_context)
|
|
||||||
.id()
|
|
||||||
.await?;
|
|
||||||
let ssr_module_id = ecmascript_client_reference
|
|
||||||
.ssr_module
|
|
||||||
.as_chunk_item(ssr_chunking_context)
|
|
||||||
.id()
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
let server_path = ecmascript_client_reference
|
|
||||||
.server_ident
|
|
||||||
.path()
|
|
||||||
.to_string()
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
let client_chunks_paths = client_chunks
|
|
||||||
.iter()
|
|
||||||
.map(|chunk| chunk.ident().path())
|
|
||||||
.try_join()
|
|
||||||
.await?;
|
|
||||||
let client_chunks_paths: Vec<String> = client_chunks_paths
|
|
||||||
.iter()
|
|
||||||
.filter_map(|chunk_path| client_relative_path.get_path_to(chunk_path))
|
|
||||||
.map(ToString::to_string)
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
|
|
||||||
let ssr_chunks_paths = ssr_chunks
|
|
||||||
.iter()
|
|
||||||
.map(|chunk| chunk.ident().path())
|
|
||||||
.try_join()
|
|
||||||
.await?;
|
|
||||||
let ssr_chunks_paths = ssr_chunks_paths
|
|
||||||
.iter()
|
|
||||||
.filter_map(|chunk_path| node_root_ref.get_path_to(chunk_path))
|
|
||||||
.map(ToString::to_string)
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
|
|
||||||
let mut ssr_manifest_node = ManifestNode::default();
|
|
||||||
|
|
||||||
entry_manifest.client_modules.module_exports.insert(
|
|
||||||
get_client_reference_module_key(&server_path, "*"),
|
|
||||||
ManifestNodeEntry {
|
|
||||||
name: "*".to_string(),
|
|
||||||
id: (&*client_module_id).into(),
|
|
||||||
chunks: client_chunks_paths.clone(),
|
|
||||||
// TODO(WEB-434)
|
|
||||||
r#async: false,
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
|
|
||||||
ssr_manifest_node.module_exports.insert(
|
all_chunks.push(entry_manifest);
|
||||||
"*".to_string(),
|
|
||||||
ManifestNodeEntry {
|
|
||||||
name: "*".to_string(),
|
|
||||||
id: (&*ssr_module_id).into(),
|
|
||||||
chunks: ssr_chunks_paths.clone(),
|
|
||||||
// TODO(WEB-434)
|
|
||||||
r#async: false,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
entry_manifest
|
|
||||||
.ssr_module_mapping
|
|
||||||
.insert((&*client_module_id).into(), ssr_manifest_node);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let client_reference_manifest_json = serde_json::to_string(&entry_manifest).unwrap();
|
|
||||||
let client_reference_manifest_source = VirtualSource::new(
|
|
||||||
node_root.join(format!(
|
|
||||||
"server/app/{original_name}_client-reference-manifest.js",
|
|
||||||
original_name = app_entry.original_name
|
|
||||||
)),
|
|
||||||
AssetContent::file(
|
|
||||||
File::from(formatdoc! {
|
|
||||||
r#"
|
|
||||||
globalThis.__RSC_MANIFEST = globalThis.__RSC_MANIFEST || {{}};
|
|
||||||
globalThis.__RSC_MANIFEST[{original_name}] = {manifest}
|
|
||||||
"#,
|
|
||||||
original_name = StringifyJs(&app_entry.original_name),
|
|
||||||
manifest = StringifyJs(&client_reference_manifest_json)
|
|
||||||
})
|
|
||||||
.into(),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
all_chunks.push(Vc::upcast(RawOutput::new(Vc::upcast(
|
|
||||||
client_reference_manifest_source,
|
|
||||||
))));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
|
||||||
pub async fn get_app_shared_client_chunk(
|
|
||||||
app_client_runtime_entries: Vc<EvaluatableAssets>,
|
|
||||||
client_chunking_context: Vc<Box<dyn EcmascriptChunkingContext>>,
|
|
||||||
) -> Result<Vc<EcmascriptChunk>> {
|
|
||||||
let client_runtime_entries: Vec<_> = app_client_runtime_entries
|
|
||||||
.await?
|
|
||||||
.iter()
|
|
||||||
.map(|entry| async move {
|
|
||||||
Ok(Vc::try_resolve_sidecast::<Box<dyn EcmascriptChunkPlaceable>>(*entry).await?)
|
|
||||||
})
|
|
||||||
.try_join()
|
|
||||||
.await?
|
|
||||||
.into_iter()
|
|
||||||
.flatten()
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
Ok(EcmascriptChunk::new_normalized(
|
|
||||||
client_chunking_context,
|
|
||||||
// TODO(alexkirsz) Should this accept Evaluatable instead?
|
|
||||||
Vc::cell(client_runtime_entries),
|
|
||||||
None,
|
|
||||||
Value::new(AvailabilityInfo::Untracked),
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
#[turbo_tasks::function]
|
|
||||||
pub async fn get_app_client_shared_chunks(
|
|
||||||
app_client_runtime_entries: Vc<EvaluatableAssets>,
|
|
||||||
client_chunking_context: Vc<Box<dyn EcmascriptChunkingContext>>,
|
|
||||||
) -> Result<Vc<OutputAssets>> {
|
|
||||||
if app_client_runtime_entries.await?.is_empty() {
|
|
||||||
return Ok(OutputAssets::empty());
|
|
||||||
}
|
|
||||||
|
|
||||||
let app_client_shared_chunk =
|
|
||||||
get_app_shared_client_chunk(app_client_runtime_entries, client_chunking_context);
|
|
||||||
|
|
||||||
let app_client_shared_chunks = client_chunking_context.evaluated_chunk_group(
|
|
||||||
Vc::upcast(app_client_shared_chunk),
|
|
||||||
app_client_runtime_entries,
|
|
||||||
);
|
|
||||||
|
|
||||||
Ok(app_client_shared_chunks)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// See next.js/packages/next/src/lib/client-reference.ts
|
|
||||||
fn get_client_reference_module_key(server_path: &str, export_name: &str) -> String {
|
|
||||||
if export_name == "*" {
|
|
||||||
server_path.to_string()
|
|
||||||
} else {
|
|
||||||
format!("{}#{}", server_path, export_name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<&TurbopackModuleId> for ModuleId {
|
|
||||||
fn from(module_id: &TurbopackModuleId) -> Self {
|
|
||||||
match module_id {
|
|
||||||
TurbopackModuleId::String(string) => ModuleId::String(string.clone()),
|
|
||||||
TurbopackModuleId::Number(number) => ModuleId::Number(*number as _),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,5 +1 @@
|
||||||
pub(crate) mod app_client_reference;
|
|
||||||
pub(crate) mod app_entries;
|
pub(crate) mod app_entries;
|
||||||
pub(crate) mod app_page_entry;
|
|
||||||
pub(crate) mod app_route_entry;
|
|
||||||
pub(crate) mod app_route_favicon_entry;
|
|
||||||
|
|
|
@ -8,10 +8,16 @@ use anyhow::{anyhow, bail, Context, Result};
|
||||||
use dunce::canonicalize;
|
use dunce::canonicalize;
|
||||||
use next_core::{
|
use next_core::{
|
||||||
mode::NextMode,
|
mode::NextMode,
|
||||||
|
next_app::get_app_client_references_chunks,
|
||||||
next_client::{get_client_chunking_context, get_client_compile_time_info},
|
next_client::{get_client_chunking_context, get_client_compile_time_info},
|
||||||
next_client_reference::{ClientReferenceType, ClientReferencesByEntry},
|
next_client_reference::{ClientReferenceGraph, ClientReferenceType},
|
||||||
next_config::load_next_config,
|
next_config::load_next_config,
|
||||||
next_dynamic::NextDynamicEntries,
|
next_dynamic::NextDynamicEntries,
|
||||||
|
next_manifests::{
|
||||||
|
AppBuildManifest, AppPathsManifest, BuildManifest, ClientBuildManifest, FontManifest,
|
||||||
|
MiddlewaresManifest, NextFontManifest, PagesManifest, ReactLoadableManifest,
|
||||||
|
ServerReferenceManifest,
|
||||||
|
},
|
||||||
next_server::{get_server_chunking_context, get_server_compile_time_info},
|
next_server::{get_server_chunking_context, get_server_compile_time_info},
|
||||||
url_node::get_sorted_routes,
|
url_node::get_sorted_routes,
|
||||||
{self},
|
{self},
|
||||||
|
@ -45,15 +51,7 @@ use turbopack_binding::{
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
build_options::{BuildContext, BuildOptions},
|
build_options::{BuildContext, BuildOptions},
|
||||||
manifests::{
|
next_app::app_entries::{compute_app_entries_chunks, get_app_entries},
|
||||||
AppBuildManifest, AppPathsManifest, BuildManifest, ClientBuildManifest, FontManifest,
|
|
||||||
MiddlewaresManifest, NextFontManifest, PagesManifest, ReactLoadableManifest,
|
|
||||||
ServerReferenceManifest,
|
|
||||||
},
|
|
||||||
next_app::{
|
|
||||||
app_client_reference::compute_app_client_references_chunks,
|
|
||||||
app_entries::{compute_app_entries_chunks, get_app_entries},
|
|
||||||
},
|
|
||||||
next_pages::page_entries::{compute_page_entries_chunks, get_page_entries},
|
next_pages::page_entries::{compute_page_entries_chunks, get_page_entries},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -167,26 +165,16 @@ pub(crate) async fn next_build(options: TransientInstance<BuildOptions>) -> Resu
|
||||||
.try_join()
|
.try_join()
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
let app_client_references_by_entry = ClientReferencesByEntry::new(Vc::cell(
|
let app_client_references = ClientReferenceGraph::new(Vc::cell(
|
||||||
app_rsc_entries.iter().copied().map(Vc::upcast).collect(),
|
app_rsc_entries.iter().copied().map(Vc::upcast).collect(),
|
||||||
))
|
));
|
||||||
.await?;
|
|
||||||
|
|
||||||
let app_client_references: HashSet<_> = app_client_references_by_entry
|
|
||||||
.values()
|
|
||||||
.flatten()
|
|
||||||
.copied()
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
// The same client reference can occur from two different server components.
|
// The same client reference can occur from two different server components.
|
||||||
// Here, we're only interested in deduped client references.
|
// Here, we're only interested in deduped client references.
|
||||||
let app_client_reference_tys: HashSet<_> = app_client_references
|
let app_client_reference_tys = app_client_references.types();
|
||||||
.iter()
|
|
||||||
.map(|client_reference| client_reference.ty())
|
|
||||||
.copied()
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
let app_ssr_entries: Vec<_> = app_client_reference_tys
|
let app_ssr_entries: Vec<_> = app_client_reference_tys
|
||||||
|
.await?
|
||||||
.iter()
|
.iter()
|
||||||
.map(|client_reference_ty| async move {
|
.map(|client_reference_ty| async move {
|
||||||
let ClientReferenceType::EcmascriptClientReference(entry) = client_reference_ty else {
|
let ClientReferenceType::EcmascriptClientReference(entry) = client_reference_ty else {
|
||||||
|
@ -298,26 +286,32 @@ pub(crate) async fn next_build(options: TransientInstance<BuildOptions>) -> Resu
|
||||||
|
|
||||||
// APP CLIENT REFERENCES CHUNKING
|
// APP CLIENT REFERENCES CHUNKING
|
||||||
|
|
||||||
let app_client_references_chunks = compute_app_client_references_chunks(
|
let app_client_references_chunks = get_app_client_references_chunks(
|
||||||
&app_client_reference_tys,
|
app_client_reference_tys,
|
||||||
client_chunking_context,
|
client_chunking_context,
|
||||||
ssr_chunking_context,
|
ssr_chunking_context,
|
||||||
&mut all_chunks,
|
);
|
||||||
)
|
let app_client_references_chunks_ref = app_client_references_chunks.await?;
|
||||||
.await?;
|
|
||||||
|
for app_client_reference_chunks in app_client_references_chunks_ref.values() {
|
||||||
|
let client_chunks = &app_client_reference_chunks.client_chunks.await?;
|
||||||
|
let ssr_chunks = &app_client_reference_chunks.ssr_chunks.await?;
|
||||||
|
all_chunks.extend(client_chunks.iter().copied());
|
||||||
|
all_chunks.extend(ssr_chunks.iter().copied());
|
||||||
|
}
|
||||||
|
|
||||||
// APP RSC CHUNKING
|
// APP RSC CHUNKING
|
||||||
// TODO(alexkirsz) Do some of that in parallel with the above.
|
// TODO(alexkirsz) Do some of that in parallel with the above.
|
||||||
|
|
||||||
compute_app_entries_chunks(
|
compute_app_entries_chunks(
|
||||||
&app_entries,
|
&app_entries,
|
||||||
&app_client_references_by_entry,
|
app_client_references,
|
||||||
&app_client_references_chunks,
|
app_client_references_chunks,
|
||||||
rsc_chunking_context,
|
rsc_chunking_context,
|
||||||
client_chunking_context,
|
client_chunking_context,
|
||||||
Vc::upcast(ssr_chunking_context),
|
Vc::upcast(ssr_chunking_context),
|
||||||
node_root,
|
node_root,
|
||||||
&client_relative_path_ref,
|
client_relative_path,
|
||||||
&app_paths_manifest_dir_path,
|
&app_paths_manifest_dir_path,
|
||||||
&mut app_build_manifest,
|
&mut app_build_manifest,
|
||||||
&mut build_manifest,
|
&mut build_manifest,
|
||||||
|
|
|
@ -8,6 +8,7 @@ use next_core::{
|
||||||
},
|
},
|
||||||
next_config::NextConfig,
|
next_config::NextConfig,
|
||||||
next_dynamic::NextDynamicTransition,
|
next_dynamic::NextDynamicTransition,
|
||||||
|
next_manifests::{BuildManifest, PagesManifest},
|
||||||
next_server::{
|
next_server::{
|
||||||
get_server_module_options_context, get_server_resolve_options_context,
|
get_server_module_options_context, get_server_resolve_options_context,
|
||||||
get_server_runtime_entries, ServerContextType,
|
get_server_runtime_entries, ServerContextType,
|
||||||
|
@ -41,8 +42,6 @@ use turbopack_binding::{
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::manifests::{BuildManifest, PagesManifest};
|
|
||||||
|
|
||||||
#[turbo_tasks::value]
|
#[turbo_tasks::value]
|
||||||
pub struct PageEntries {
|
pub struct PageEntries {
|
||||||
pub entries: Vec<Vc<PageEntry>>,
|
pub entries: Vec<Vc<PageEntry>>,
|
||||||
|
|
|
@ -12,6 +12,7 @@ bench = false
|
||||||
anyhow = { workspace = true }
|
anyhow = { workspace = true }
|
||||||
async-recursion = { workspace = true }
|
async-recursion = { workspace = true }
|
||||||
async-trait = { workspace = true }
|
async-trait = { workspace = true }
|
||||||
|
base64 = "0.21.0"
|
||||||
const_format = "0.2.30"
|
const_format = "0.2.30"
|
||||||
once_cell = { workspace = true }
|
once_cell = { workspace = true }
|
||||||
qstring = { workspace = true }
|
qstring = { workspace = true }
|
||||||
|
@ -20,6 +21,7 @@ serde = { workspace = true }
|
||||||
serde_json = { workspace = true }
|
serde_json = { workspace = true }
|
||||||
indexmap = { workspace = true, features = ["serde"] }
|
indexmap = { workspace = true, features = ["serde"] }
|
||||||
mime = { workspace = true }
|
mime = { workspace = true }
|
||||||
|
mime_guess = "2.0.4"
|
||||||
indoc = { workspace = true }
|
indoc = { workspace = true }
|
||||||
allsorts = { workspace = true }
|
allsorts = { workspace = true }
|
||||||
futures = { workspace = true }
|
futures = { workspace = true }
|
||||||
|
|
|
@ -10,8 +10,8 @@
|
||||||
"check": "tsc --noEmit"
|
"check": "tsc --noEmit"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@vercel/turbopack-ecmascript-runtime": "https://gitpkg-fork.vercel.sh/vercel/turbo/crates/turbopack-ecmascript-runtime/js?turbopack-230716.2",
|
"@vercel/turbopack-ecmascript-runtime": "https://gitpkg-fork.vercel.sh/vercel/turbo/crates/turbopack-ecmascript-runtime/js?turbopack-230717.2",
|
||||||
"@vercel/turbopack-node": "https://gitpkg-fork.vercel.sh/vercel/turbo/crates/turbopack-node/js?turbopack-230716.2",
|
"@vercel/turbopack-node": "https://gitpkg-fork.vercel.sh/vercel/turbo/crates/turbopack-node/js?turbopack-230717.2",
|
||||||
"anser": "^2.1.1",
|
"anser": "^2.1.1",
|
||||||
"css.escape": "^1.5.1",
|
"css.escape": "^1.5.1",
|
||||||
"next": "*",
|
"next": "*",
|
||||||
|
|
|
@ -65,6 +65,7 @@ use crate::{
|
||||||
fallback::get_fallback_page,
|
fallback::get_fallback_page,
|
||||||
loader_tree::{LoaderTreeModule, ServerComponentTransition},
|
loader_tree::{LoaderTreeModule, ServerComponentTransition},
|
||||||
mode::NextMode,
|
mode::NextMode,
|
||||||
|
next_app::UnsupportedDynamicMetadataIssue,
|
||||||
next_client::{
|
next_client::{
|
||||||
context::{
|
context::{
|
||||||
get_client_assets_path, get_client_module_options_context,
|
get_client_assets_path, get_client_module_options_context,
|
||||||
|
@ -89,7 +90,6 @@ use crate::{
|
||||||
get_server_resolve_options_context, ServerContextType,
|
get_server_resolve_options_context, ServerContextType,
|
||||||
},
|
},
|
||||||
util::{render_data, NextRuntime},
|
util::{render_data, NextRuntime},
|
||||||
UnsupportedDynamicMetadataIssue,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
fn pathname_to_segments(pathname: &str) -> Result<(Vec<BaseSegment>, RouteType)> {
|
fn pathname_to_segments(pathname: &str) -> Result<(Vec<BaseSegment>, RouteType)> {
|
||||||
|
|
|
@ -94,7 +94,7 @@ pub enum MetadataWithAltItem {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A single metadata file.
|
/// A single metadata file.
|
||||||
#[derive(Copy, Clone, Debug, Serialize, Deserialize, PartialEq, Eq, TraceRawVcs)]
|
#[derive(Copy, Clone, Debug, Serialize, Deserialize, PartialEq, Eq, TaskInput, TraceRawVcs)]
|
||||||
pub enum MetadataItem {
|
pub enum MetadataItem {
|
||||||
Static { path: Vc<FileSystemPath> },
|
Static { path: Vc<FileSystemPath> },
|
||||||
Dynamic { path: Vc<FileSystemPath> },
|
Dynamic { path: Vc<FileSystemPath> },
|
||||||
|
|
|
@ -12,6 +12,9 @@ use turbopack_binding::turbopack::core::{
|
||||||
|
|
||||||
/// Emits all assets transitively reachable from the given chunks, that are
|
/// Emits all assets transitively reachable from the given chunks, that are
|
||||||
/// inside the node root or the client root.
|
/// inside the node root or the client root.
|
||||||
|
///
|
||||||
|
/// Assets inside the given client root are rebased to the given client output
|
||||||
|
/// path.
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
pub async fn emit_all_assets(
|
pub async fn emit_all_assets(
|
||||||
assets: Vc<OutputAssets>,
|
assets: Vc<OutputAssets>,
|
||||||
|
|
|
@ -12,14 +12,14 @@ mod app_source;
|
||||||
pub mod app_structure;
|
pub mod app_structure;
|
||||||
mod babel;
|
mod babel;
|
||||||
mod bootstrap;
|
mod bootstrap;
|
||||||
|
pub mod dev_manifest;
|
||||||
mod embed_js;
|
mod embed_js;
|
||||||
mod emit;
|
mod emit;
|
||||||
pub mod env;
|
pub mod env;
|
||||||
mod fallback;
|
mod fallback;
|
||||||
pub mod loader_tree;
|
pub mod loader_tree;
|
||||||
pub mod manifest;
|
|
||||||
pub mod mode;
|
pub mod mode;
|
||||||
pub(crate) mod next_app;
|
pub mod next_app;
|
||||||
mod next_build;
|
mod next_build;
|
||||||
pub mod next_client;
|
pub mod next_client;
|
||||||
pub mod next_client_chunks;
|
pub mod next_client_chunks;
|
||||||
|
@ -31,6 +31,7 @@ mod next_edge;
|
||||||
mod next_font;
|
mod next_font;
|
||||||
pub mod next_image;
|
pub mod next_image;
|
||||||
mod next_import_map;
|
mod next_import_map;
|
||||||
|
pub mod next_manifests;
|
||||||
mod next_route_matcher;
|
mod next_route_matcher;
|
||||||
pub mod next_server;
|
pub mod next_server;
|
||||||
pub mod next_server_component;
|
pub mod next_server_component;
|
||||||
|
@ -49,7 +50,6 @@ mod web_entry_source;
|
||||||
|
|
||||||
pub use app_source::create_app_source;
|
pub use app_source::create_app_source;
|
||||||
pub use emit::emit_all_assets;
|
pub use emit::emit_all_assets;
|
||||||
pub use next_app::unsupported_dynamic_metadata_issue::UnsupportedDynamicMetadataIssue;
|
|
||||||
pub use page_loader::create_page_loader_entry_module;
|
pub use page_loader::create_page_loader_entry_module;
|
||||||
pub use page_source::create_page_source;
|
pub use page_source::create_page_source;
|
||||||
pub use turbopack_binding::{turbopack::node::source_map, *};
|
pub use turbopack_binding::{turbopack::node::source_map, *};
|
||||||
|
|
|
@ -1,33 +1,44 @@
|
||||||
use std::collections::HashSet;
|
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
use next_core::{
|
use serde::{Deserialize, Serialize};
|
||||||
next_client_reference::ClientReferenceType,
|
use turbo_tasks::{debug::ValueDebugFormat, trace::TraceRawVcs, TryJoinIterExt, Vc};
|
||||||
{self},
|
|
||||||
};
|
|
||||||
use turbo_tasks::{TryJoinIterExt, Vc};
|
|
||||||
use turbopack_binding::turbopack::{
|
use turbopack_binding::turbopack::{
|
||||||
build::BuildChunkingContext,
|
build::BuildChunkingContext,
|
||||||
core::{
|
core::{
|
||||||
chunk::{ChunkableModule, ChunkingContext},
|
chunk::{ChunkableModule, ChunkingContext},
|
||||||
output::{OutputAsset, OutputAssets},
|
output::OutputAssets,
|
||||||
},
|
},
|
||||||
ecmascript::chunk::EcmascriptChunkingContext,
|
ecmascript::chunk::EcmascriptChunkingContext,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Computes all client references chunks, and adds them to the relevant
|
use crate::next_client_reference::{ClientReferenceType, ClientReferenceTypes};
|
||||||
/// manifests.
|
|
||||||
|
/// Contains the chunks corresponding to a client reference.
|
||||||
|
#[derive(
|
||||||
|
Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, TraceRawVcs, ValueDebugFormat,
|
||||||
|
)]
|
||||||
|
pub struct ClientReferenceChunks {
|
||||||
|
/// Chunks to be loaded on the client.
|
||||||
|
pub client_chunks: Vc<OutputAssets>,
|
||||||
|
/// Chunks to be loaded on the server for SSR.
|
||||||
|
pub ssr_chunks: Vc<OutputAssets>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[turbo_tasks::value(transparent)]
|
||||||
|
pub struct ClientReferencesChunks(IndexMap<ClientReferenceType, ClientReferenceChunks>);
|
||||||
|
|
||||||
|
/// Computes all client references chunks.
|
||||||
///
|
///
|
||||||
/// This returns a map from client reference type to the chunks that reference
|
/// This returns a map from client reference type to the chunks that reference
|
||||||
/// type needs to load.
|
/// type needs to load.
|
||||||
pub async fn compute_app_client_references_chunks(
|
#[turbo_tasks::function]
|
||||||
app_client_reference_types: &HashSet<ClientReferenceType>,
|
pub async fn get_app_client_references_chunks(
|
||||||
|
app_client_reference_types: Vc<ClientReferenceTypes>,
|
||||||
client_chunking_context: Vc<Box<dyn EcmascriptChunkingContext>>,
|
client_chunking_context: Vc<Box<dyn EcmascriptChunkingContext>>,
|
||||||
ssr_chunking_context: Vc<BuildChunkingContext>,
|
ssr_chunking_context: Vc<BuildChunkingContext>,
|
||||||
all_chunks: &mut Vec<Vc<Box<dyn OutputAsset>>>,
|
) -> Result<Vc<ClientReferencesChunks>> {
|
||||||
) -> Result<IndexMap<ClientReferenceType, ClientReferenceChunks>> {
|
|
||||||
let app_client_references_chunks: IndexMap<_, _> = app_client_reference_types
|
let app_client_references_chunks: IndexMap<_, _> = app_client_reference_types
|
||||||
|
.await?
|
||||||
.iter()
|
.iter()
|
||||||
.map(|client_reference_ty| async move {
|
.map(|client_reference_ty| async move {
|
||||||
Ok((
|
Ok((
|
||||||
|
@ -64,28 +75,5 @@ pub async fn compute_app_client_references_chunks(
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
for (app_client_reference_ty, app_client_reference_chunks) in &app_client_references_chunks {
|
Ok(Vc::cell(app_client_references_chunks))
|
||||||
match app_client_reference_ty {
|
|
||||||
ClientReferenceType::EcmascriptClientReference(_) => {
|
|
||||||
let client_chunks = &app_client_reference_chunks.client_chunks.await?;
|
|
||||||
let ssr_chunks = &app_client_reference_chunks.ssr_chunks.await?;
|
|
||||||
all_chunks.extend(client_chunks.iter().copied());
|
|
||||||
all_chunks.extend(ssr_chunks.iter().copied());
|
|
||||||
}
|
|
||||||
ClientReferenceType::CssClientReference(_) => {
|
|
||||||
let client_chunks = &app_client_reference_chunks.client_chunks.await?;
|
|
||||||
all_chunks.extend(client_chunks.iter().copied());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(app_client_references_chunks)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Contains the chunks corresponding to a client reference.
|
|
||||||
pub struct ClientReferenceChunks {
|
|
||||||
/// Chunks to be loaded on the client.
|
|
||||||
pub client_chunks: Vc<OutputAssets>,
|
|
||||||
/// Chunks to be loaded on the server for SSR.
|
|
||||||
pub ssr_chunks: Vc<OutputAssets>,
|
|
||||||
}
|
}
|
|
@ -0,0 +1,55 @@
|
||||||
|
use anyhow::Result;
|
||||||
|
use turbo_tasks::{TryJoinIterExt, Value, Vc};
|
||||||
|
use turbopack_binding::turbopack::{
|
||||||
|
core::{
|
||||||
|
chunk::{availability_info::AvailabilityInfo, ChunkingContext, EvaluatableAssets},
|
||||||
|
output::OutputAssets,
|
||||||
|
},
|
||||||
|
ecmascript::chunk::{EcmascriptChunk, EcmascriptChunkPlaceable, EcmascriptChunkingContext},
|
||||||
|
};
|
||||||
|
|
||||||
|
#[turbo_tasks::function]
|
||||||
|
pub async fn get_app_shared_client_chunk(
|
||||||
|
app_client_runtime_entries: Vc<EvaluatableAssets>,
|
||||||
|
client_chunking_context: Vc<Box<dyn EcmascriptChunkingContext>>,
|
||||||
|
) -> Result<Vc<EcmascriptChunk>> {
|
||||||
|
let client_runtime_entries: Vec<_> = app_client_runtime_entries
|
||||||
|
.await?
|
||||||
|
.iter()
|
||||||
|
.map(|entry| async move {
|
||||||
|
Ok(Vc::try_resolve_sidecast::<Box<dyn EcmascriptChunkPlaceable>>(*entry).await?)
|
||||||
|
})
|
||||||
|
.try_join()
|
||||||
|
.await?
|
||||||
|
.into_iter()
|
||||||
|
.flatten()
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
Ok(EcmascriptChunk::new_normalized(
|
||||||
|
client_chunking_context,
|
||||||
|
// TODO(alexkirsz) Should this accept Evaluatable instead?
|
||||||
|
Vc::cell(client_runtime_entries),
|
||||||
|
None,
|
||||||
|
Value::new(AvailabilityInfo::Untracked),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[turbo_tasks::function]
|
||||||
|
pub async fn get_app_client_shared_chunks(
|
||||||
|
app_client_runtime_entries: Vc<EvaluatableAssets>,
|
||||||
|
client_chunking_context: Vc<Box<dyn EcmascriptChunkingContext>>,
|
||||||
|
) -> Result<Vc<OutputAssets>> {
|
||||||
|
if app_client_runtime_entries.await?.is_empty() {
|
||||||
|
return Ok(OutputAssets::empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
let app_client_shared_chunk =
|
||||||
|
get_app_shared_client_chunk(app_client_runtime_entries, client_chunking_context);
|
||||||
|
|
||||||
|
let app_client_shared_chunks = client_chunking_context.evaluated_chunk_group(
|
||||||
|
Vc::upcast(app_client_shared_chunk),
|
||||||
|
app_client_runtime_entries,
|
||||||
|
);
|
||||||
|
|
||||||
|
Ok(app_client_shared_chunks)
|
||||||
|
}
|
14
packages/next-swc/crates/next-core/src/next_app/app_entry.rs
Normal file
14
packages/next-swc/crates/next-core/src/next_app/app_entry.rs
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
use turbo_tasks::Vc;
|
||||||
|
use turbopack_binding::turbopack::ecmascript::chunk::EcmascriptChunkPlaceable;
|
||||||
|
|
||||||
|
/// The entry module asset for a Next.js app route or page.
|
||||||
|
#[turbo_tasks::value(shared)]
|
||||||
|
pub struct AppEntry {
|
||||||
|
/// The pathname of the route or page.
|
||||||
|
pub pathname: String,
|
||||||
|
/// The original Next.js name of the route or page. This is used instead of
|
||||||
|
/// the pathname to refer to this entry.
|
||||||
|
pub original_name: String,
|
||||||
|
/// The RSC module asset for the route or page.
|
||||||
|
pub rsc_entry: Vc<Box<dyn EcmascriptChunkPlaceable>>,
|
||||||
|
}
|
|
@ -3,7 +3,6 @@ use std::io::Write;
|
||||||
use anyhow::{bail, Result};
|
use anyhow::{bail, Result};
|
||||||
use base64::{display::Base64Display, engine::general_purpose::STANDARD};
|
use base64::{display::Base64Display, engine::general_purpose::STANDARD};
|
||||||
use indoc::writedoc;
|
use indoc::writedoc;
|
||||||
use next_core::app_structure::MetadataItem;
|
|
||||||
use turbo_tasks::{ValueToString, Vc};
|
use turbo_tasks::{ValueToString, Vc};
|
||||||
use turbopack_binding::{
|
use turbopack_binding::{
|
||||||
turbo::tasks_fs::{rope::RopeBuilder, File, FileContent, FileSystemPath},
|
turbo::tasks_fs::{rope::RopeBuilder, File, FileContent, FileSystemPath},
|
||||||
|
@ -14,10 +13,12 @@ use turbopack_binding::{
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{app_entries::AppEntry, app_route_entry::get_app_route_entry};
|
use super::app_route_entry::get_app_route_entry;
|
||||||
|
use crate::{app_structure::MetadataItem, next_app::AppEntry};
|
||||||
|
|
||||||
/// Computes the entry for a Next.js favicon file.
|
/// Computes the entry for a Next.js favicon file.
|
||||||
pub(super) async fn get_app_route_favicon_entry(
|
#[turbo_tasks::function]
|
||||||
|
pub async fn get_app_route_favicon_entry(
|
||||||
rsc_context: Vc<ModuleAssetContext>,
|
rsc_context: Vc<ModuleAssetContext>,
|
||||||
favicon: MetadataItem,
|
favicon: MetadataItem,
|
||||||
project_root: Vc<FileSystemPath>,
|
project_root: Vc<FileSystemPath>,
|
||||||
|
@ -77,12 +78,11 @@ pub(super) async fn get_app_route_favicon_entry(
|
||||||
// TODO(alexkirsz) Figure out how to name this virtual source.
|
// TODO(alexkirsz) Figure out how to name this virtual source.
|
||||||
VirtualSource::new(project_root.join("todo.tsx".to_string()), AssetContent::file(file.into()));
|
VirtualSource::new(project_root.join("todo.tsx".to_string()), AssetContent::file(file.into()));
|
||||||
|
|
||||||
get_app_route_entry(
|
Ok(get_app_route_entry(
|
||||||
rsc_context,
|
rsc_context,
|
||||||
Vc::upcast(source),
|
Vc::upcast(source),
|
||||||
// TODO(alexkirsz) Get this from the metadata?
|
// TODO(alexkirsz) Get this from the metadata?
|
||||||
"/favicon.ico",
|
"/favicon.ico".to_string(),
|
||||||
project_root,
|
project_root,
|
||||||
)
|
))
|
||||||
.await
|
|
||||||
}
|
}
|
|
@ -2,13 +2,6 @@ use std::io::Write;
|
||||||
|
|
||||||
use anyhow::{bail, Result};
|
use anyhow::{bail, Result};
|
||||||
use indoc::writedoc;
|
use indoc::writedoc;
|
||||||
use next_core::{
|
|
||||||
app_structure::LoaderTree,
|
|
||||||
loader_tree::{LoaderTreeModule, ServerComponentTransition},
|
|
||||||
mode::NextMode,
|
|
||||||
next_server_component::NextServerComponentTransition,
|
|
||||||
UnsupportedDynamicMetadataIssue,
|
|
||||||
};
|
|
||||||
use turbo_tasks::{TryJoinIterExt, Value, ValueToString, Vc};
|
use turbo_tasks::{TryJoinIterExt, Value, ValueToString, Vc};
|
||||||
use turbopack_binding::{
|
use turbopack_binding::{
|
||||||
turbo::tasks_fs::{rope::RopeBuilder, File, FileSystemPath},
|
turbo::tasks_fs::{rope::RopeBuilder, File, FileSystemPath},
|
||||||
|
@ -22,14 +15,22 @@ use turbopack_binding::{
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::app_entries::AppEntry;
|
use super::app_entry::AppEntry;
|
||||||
|
use crate::{
|
||||||
|
app_structure::LoaderTree,
|
||||||
|
loader_tree::{LoaderTreeModule, ServerComponentTransition},
|
||||||
|
mode::NextMode,
|
||||||
|
next_app::UnsupportedDynamicMetadataIssue,
|
||||||
|
next_server_component::NextServerComponentTransition,
|
||||||
|
};
|
||||||
|
|
||||||
/// Computes the entry for a Next.js app page.
|
/// Computes the entry for a Next.js app page.
|
||||||
pub(super) async fn get_app_page_entry(
|
#[turbo_tasks::function]
|
||||||
|
pub async fn get_app_page_entry(
|
||||||
context: Vc<ModuleAssetContext>,
|
context: Vc<ModuleAssetContext>,
|
||||||
loader_tree: Vc<LoaderTree>,
|
loader_tree: Vc<LoaderTree>,
|
||||||
app_dir: Vc<FileSystemPath>,
|
app_dir: Vc<FileSystemPath>,
|
||||||
pathname: &str,
|
pathname: String,
|
||||||
project_root: Vc<FileSystemPath>,
|
project_root: Vc<FileSystemPath>,
|
||||||
) -> Result<Vc<AppEntry>> {
|
) -> Result<Vc<AppEntry>> {
|
||||||
let server_component_transition = Vc::upcast(NextServerComponentTransition::new());
|
let server_component_transition = Vc::upcast(NextServerComponentTransition::new());
|
||||||
|
@ -70,7 +71,7 @@ pub(super) async fn get_app_page_entry(
|
||||||
// NOTE(alexkirsz) Keep in sync with
|
// NOTE(alexkirsz) Keep in sync with
|
||||||
// next.js/packages/next/src/build/webpack/loaders/next-app-loader.ts
|
// next.js/packages/next/src/build/webpack/loaders/next-app-loader.ts
|
||||||
// TODO(alexkirsz) Support custom global error.
|
// TODO(alexkirsz) Support custom global error.
|
||||||
let original_name = get_original_page_name(pathname);
|
let original_name = get_original_page_name(&pathname);
|
||||||
|
|
||||||
writedoc!(
|
writedoc!(
|
||||||
result,
|
result,
|
|
@ -20,19 +20,20 @@ use turbopack_binding::{
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::app_entries::AppEntry;
|
use crate::next_app::AppEntry;
|
||||||
|
|
||||||
/// Computes the entry for a Next.js app route.
|
/// Computes the entry for a Next.js app route.
|
||||||
pub(super) async fn get_app_route_entry(
|
#[turbo_tasks::function]
|
||||||
|
pub async fn get_app_route_entry(
|
||||||
rsc_context: Vc<ModuleAssetContext>,
|
rsc_context: Vc<ModuleAssetContext>,
|
||||||
source: Vc<Box<dyn Source>>,
|
source: Vc<Box<dyn Source>>,
|
||||||
pathname: &str,
|
pathname: String,
|
||||||
project_root: Vc<FileSystemPath>,
|
project_root: Vc<FileSystemPath>,
|
||||||
) -> Result<Vc<AppEntry>> {
|
) -> Result<Vc<AppEntry>> {
|
||||||
let mut result = RopeBuilder::default();
|
let mut result = RopeBuilder::default();
|
||||||
|
|
||||||
let kind = "app-route";
|
let kind = "app-route";
|
||||||
let original_name = get_original_route_name(pathname);
|
let original_name = get_original_route_name(&pathname);
|
||||||
let path = source.ident().path();
|
let path = source.ident().path();
|
||||||
|
|
||||||
let options = AppRouteRouteModuleOptions {
|
let options = AppRouteRouteModuleOptions {
|
|
@ -1 +1,17 @@
|
||||||
|
pub(crate) mod app_client_references_chunks;
|
||||||
|
pub(crate) mod app_client_shared_chunks;
|
||||||
|
pub(crate) mod app_entry;
|
||||||
|
pub(crate) mod app_favicon_entry;
|
||||||
|
pub(crate) mod app_page_entry;
|
||||||
|
pub(crate) mod app_route_entry;
|
||||||
pub(crate) mod unsupported_dynamic_metadata_issue;
|
pub(crate) mod unsupported_dynamic_metadata_issue;
|
||||||
|
|
||||||
|
pub use app_client_references_chunks::{
|
||||||
|
get_app_client_references_chunks, ClientReferenceChunks, ClientReferencesChunks,
|
||||||
|
};
|
||||||
|
pub use app_client_shared_chunks::get_app_client_shared_chunks;
|
||||||
|
pub use app_entry::AppEntry;
|
||||||
|
pub use app_favicon_entry::get_app_route_favicon_entry;
|
||||||
|
pub use app_page_entry::get_app_page_entry;
|
||||||
|
pub use app_route_entry::get_app_route_entry;
|
||||||
|
pub use unsupported_dynamic_metadata_issue::UnsupportedDynamicMetadataIssue;
|
||||||
|
|
|
@ -7,4 +7,7 @@ pub use ecmascript_client_reference::{
|
||||||
ecmascript_client_reference_module::EcmascriptClientReferenceModule,
|
ecmascript_client_reference_module::EcmascriptClientReferenceModule,
|
||||||
ecmascript_client_reference_transition::NextEcmascriptClientReferenceTransition,
|
ecmascript_client_reference_transition::NextEcmascriptClientReferenceTransition,
|
||||||
};
|
};
|
||||||
pub use visit_client_reference::{ClientReference, ClientReferenceType, ClientReferencesByEntry};
|
pub use visit_client_reference::{
|
||||||
|
ClientReference, ClientReferenceGraph, ClientReferenceType, ClientReferenceTypes,
|
||||||
|
ClientReferences,
|
||||||
|
};
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use std::future::Future;
|
use std::future::Future;
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use indexmap::IndexMap;
|
use indexmap::IndexSet;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use turbo_tasks::{
|
use turbo_tasks::{
|
||||||
debug::ValueDebugFormat,
|
debug::ValueDebugFormat,
|
||||||
|
@ -47,12 +47,20 @@ pub enum ClientReferenceType {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[turbo_tasks::value(transparent)]
|
#[turbo_tasks::value(transparent)]
|
||||||
pub struct ClientReferencesByEntry(IndexMap<Vc<Box<dyn Asset>>, Vec<ClientReference>>);
|
pub struct ClientReferences(Vec<ClientReference>);
|
||||||
|
|
||||||
|
#[turbo_tasks::value(transparent)]
|
||||||
|
pub struct ClientReferenceTypes(IndexSet<ClientReferenceType>);
|
||||||
|
|
||||||
|
#[turbo_tasks::value(transparent)]
|
||||||
|
pub struct ClientReferenceGraph {
|
||||||
|
graph: AdjacencyMap<VisitClientReferenceNode>,
|
||||||
|
}
|
||||||
|
|
||||||
#[turbo_tasks::value_impl]
|
#[turbo_tasks::value_impl]
|
||||||
impl ClientReferencesByEntry {
|
impl ClientReferenceGraph {
|
||||||
#[turbo_tasks::function]
|
#[turbo_tasks::function]
|
||||||
pub async fn new(entries: Vc<Assets>) -> Result<Vc<ClientReferencesByEntry>> {
|
pub async fn new(entries: Vc<Assets>) -> Result<Vc<Self>> {
|
||||||
let entries = entries.await?;
|
let entries = entries.await?;
|
||||||
|
|
||||||
let graph = AdjacencyMap::new()
|
let graph = AdjacencyMap::new()
|
||||||
|
@ -72,15 +80,41 @@ impl ClientReferencesByEntry {
|
||||||
.completed()?
|
.completed()?
|
||||||
.into_inner();
|
.into_inner();
|
||||||
|
|
||||||
let client_references = entries
|
Ok(ClientReferenceGraph { graph }.cell())
|
||||||
.iter()
|
}
|
||||||
.copied()
|
|
||||||
.map(|entry| {
|
#[turbo_tasks::function]
|
||||||
|
pub async fn types(self: Vc<Self>) -> Result<Vc<ClientReferenceTypes>> {
|
||||||
|
let this = self.await?;
|
||||||
|
let mut client_reference_types = IndexSet::new();
|
||||||
|
|
||||||
|
for node in this.graph.reverse_topological() {
|
||||||
|
match &node.ty {
|
||||||
|
VisitClientReferenceNodeType::Internal(_asset) => {
|
||||||
|
// No-op. These nodes are only useful during graph
|
||||||
|
// traversal.
|
||||||
|
}
|
||||||
|
VisitClientReferenceNodeType::ClientReference(client_reference) => {
|
||||||
|
client_reference_types.insert(*client_reference.ty());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(Vc::cell(client_reference_types))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[turbo_tasks::function]
|
||||||
|
pub async fn entry(self: Vc<Self>, entry: Vc<Box<dyn Asset>>) -> Result<Vc<ClientReferences>> {
|
||||||
|
let this = self.await?;
|
||||||
let mut entry_client_references = vec![];
|
let mut entry_client_references = vec![];
|
||||||
for node in graph.reverse_topological_from_node(&VisitClientReferenceNode {
|
|
||||||
|
for node in this
|
||||||
|
.graph
|
||||||
|
.reverse_topological_from_node(&VisitClientReferenceNode {
|
||||||
server_component: None,
|
server_component: None,
|
||||||
ty: VisitClientReferenceNodeType::Internal(entry),
|
ty: VisitClientReferenceNodeType::Internal(entry),
|
||||||
}) {
|
})
|
||||||
|
{
|
||||||
match &node.ty {
|
match &node.ty {
|
||||||
VisitClientReferenceNodeType::Internal(_asset) => {
|
VisitClientReferenceNodeType::Internal(_asset) => {
|
||||||
// No-op. These nodes are only useful during graph
|
// No-op. These nodes are only useful during graph
|
||||||
|
@ -91,23 +125,24 @@ impl ClientReferencesByEntry {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(entry, entry_client_references)
|
|
||||||
})
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
Ok(Vc::cell(client_references))
|
Ok(Vc::cell(entry_client_references))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct VisitClientReference;
|
struct VisitClientReference;
|
||||||
|
|
||||||
#[derive(Clone, Eq, PartialEq, Hash)]
|
#[derive(
|
||||||
|
Clone, Eq, PartialEq, Hash, Serialize, Deserialize, Debug, ValueDebugFormat, TraceRawVcs,
|
||||||
|
)]
|
||||||
struct VisitClientReferenceNode {
|
struct VisitClientReferenceNode {
|
||||||
server_component: Option<Vc<NextServerComponentModule>>,
|
server_component: Option<Vc<NextServerComponentModule>>,
|
||||||
ty: VisitClientReferenceNodeType,
|
ty: VisitClientReferenceNodeType,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Eq, PartialEq, Hash)]
|
#[derive(
|
||||||
|
Clone, Eq, PartialEq, Hash, Serialize, Deserialize, Debug, ValueDebugFormat, TraceRawVcs,
|
||||||
|
)]
|
||||||
enum VisitClientReferenceNodeType {
|
enum VisitClientReferenceNodeType {
|
||||||
ClientReference(ClientReference),
|
ClientReference(ClientReference),
|
||||||
Internal(Vc<Box<dyn Asset>>),
|
Internal(Vc<Box<dyn Asset>>),
|
||||||
|
|
|
@ -0,0 +1,217 @@
|
||||||
|
use anyhow::{Context, Result};
|
||||||
|
use indoc::formatdoc;
|
||||||
|
use turbo_tasks::{TryJoinIterExt, ValueToString, Vc};
|
||||||
|
use turbo_tasks_fs::{File, FileSystemPath};
|
||||||
|
use turbopack_binding::turbopack::{
|
||||||
|
core::{
|
||||||
|
asset::{Asset, AssetContent},
|
||||||
|
chunk::ModuleId as TurbopackModuleId,
|
||||||
|
output::OutputAsset,
|
||||||
|
raw_output::RawOutput,
|
||||||
|
virtual_source::VirtualSource,
|
||||||
|
},
|
||||||
|
ecmascript::{
|
||||||
|
chunk::{EcmascriptChunkItemExt, EcmascriptChunkPlaceable, EcmascriptChunkingContext},
|
||||||
|
utils::StringifyJs,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
use super::{ClientReferenceManifest, ManifestNode, ManifestNodeEntry, ModuleId};
|
||||||
|
use crate::{
|
||||||
|
next_app::ClientReferencesChunks,
|
||||||
|
next_client_reference::{ClientReferenceType, ClientReferences},
|
||||||
|
};
|
||||||
|
|
||||||
|
#[turbo_tasks::value_impl]
|
||||||
|
impl ClientReferenceManifest {
|
||||||
|
#[turbo_tasks::function]
|
||||||
|
pub async fn build_output(
|
||||||
|
node_root: Vc<FileSystemPath>,
|
||||||
|
client_relative_path: Vc<FileSystemPath>,
|
||||||
|
entry_name: String,
|
||||||
|
client_references: Vc<ClientReferences>,
|
||||||
|
client_references_chunks: Vc<ClientReferencesChunks>,
|
||||||
|
client_chunking_context: Vc<Box<dyn EcmascriptChunkingContext>>,
|
||||||
|
ssr_chunking_context: Vc<Box<dyn EcmascriptChunkingContext>>,
|
||||||
|
) -> Result<Vc<Box<dyn OutputAsset>>> {
|
||||||
|
let mut entry_manifest: ClientReferenceManifest = Default::default();
|
||||||
|
let client_references_chunks = client_references_chunks.await?;
|
||||||
|
let client_relative_path = client_relative_path.await?;
|
||||||
|
let node_root_ref = node_root.await?;
|
||||||
|
|
||||||
|
for app_client_reference in client_references.await?.iter() {
|
||||||
|
let app_client_reference_ty = app_client_reference.ty();
|
||||||
|
|
||||||
|
let app_client_reference_chunks = client_references_chunks
|
||||||
|
.get(app_client_reference.ty())
|
||||||
|
.context("client reference chunks not found")?;
|
||||||
|
|
||||||
|
let client_reference_chunks = client_references_chunks
|
||||||
|
.get(app_client_reference_ty)
|
||||||
|
.context("client reference chunks not found")?;
|
||||||
|
let client_chunks = &client_reference_chunks.client_chunks.await?;
|
||||||
|
|
||||||
|
let client_chunks_paths = client_chunks
|
||||||
|
.iter()
|
||||||
|
.map(|chunk| chunk.ident().path())
|
||||||
|
.try_join()
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
if let Some(server_component) = app_client_reference.server_component() {
|
||||||
|
let server_component_name = server_component
|
||||||
|
.server_path()
|
||||||
|
.with_extension("".to_string())
|
||||||
|
.to_string()
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
let entry_css_files = entry_manifest
|
||||||
|
.entry_css_files
|
||||||
|
.entry(server_component_name.clone_value())
|
||||||
|
.or_insert_with(Default::default);
|
||||||
|
|
||||||
|
match app_client_reference_ty {
|
||||||
|
ClientReferenceType::CssClientReference(_) => {
|
||||||
|
entry_css_files.extend(
|
||||||
|
client_chunks_paths
|
||||||
|
.iter()
|
||||||
|
.filter_map(|chunk_path| {
|
||||||
|
client_relative_path.get_path_to(chunk_path)
|
||||||
|
})
|
||||||
|
.map(ToString::to_string),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
ClientReferenceType::EcmascriptClientReference(_) => {
|
||||||
|
entry_css_files.extend(
|
||||||
|
client_chunks_paths
|
||||||
|
.iter()
|
||||||
|
.filter_map(|chunk_path| {
|
||||||
|
if chunk_path.extension_ref() == Some("css") {
|
||||||
|
client_relative_path.get_path_to(chunk_path)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.map(ToString::to_string),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
match app_client_reference_ty {
|
||||||
|
ClientReferenceType::CssClientReference(_) => {}
|
||||||
|
|
||||||
|
ClientReferenceType::EcmascriptClientReference(ecmascript_client_reference) => {
|
||||||
|
let client_chunks = &app_client_reference_chunks.client_chunks.await?;
|
||||||
|
let ssr_chunks = &app_client_reference_chunks.ssr_chunks.await?;
|
||||||
|
|
||||||
|
let ecmascript_client_reference = ecmascript_client_reference.await?;
|
||||||
|
|
||||||
|
let client_module_id = ecmascript_client_reference
|
||||||
|
.client_module
|
||||||
|
.as_chunk_item(client_chunking_context)
|
||||||
|
.id()
|
||||||
|
.await?;
|
||||||
|
let ssr_module_id = ecmascript_client_reference
|
||||||
|
.ssr_module
|
||||||
|
.as_chunk_item(ssr_chunking_context)
|
||||||
|
.id()
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
let server_path = ecmascript_client_reference
|
||||||
|
.server_ident
|
||||||
|
.path()
|
||||||
|
.to_string()
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
let client_chunks_paths = client_chunks
|
||||||
|
.iter()
|
||||||
|
.map(|chunk| chunk.ident().path())
|
||||||
|
.try_join()
|
||||||
|
.await?;
|
||||||
|
let client_chunks_paths: Vec<String> = client_chunks_paths
|
||||||
|
.iter()
|
||||||
|
.filter_map(|chunk_path| client_relative_path.get_path_to(chunk_path))
|
||||||
|
.map(ToString::to_string)
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
let ssr_chunks_paths = ssr_chunks
|
||||||
|
.iter()
|
||||||
|
.map(|chunk| chunk.ident().path())
|
||||||
|
.try_join()
|
||||||
|
.await?;
|
||||||
|
let ssr_chunks_paths = ssr_chunks_paths
|
||||||
|
.iter()
|
||||||
|
.filter_map(|chunk_path| node_root_ref.get_path_to(chunk_path))
|
||||||
|
.map(ToString::to_string)
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
let mut ssr_manifest_node = ManifestNode::default();
|
||||||
|
|
||||||
|
entry_manifest.client_modules.module_exports.insert(
|
||||||
|
get_client_reference_module_key(&server_path, "*"),
|
||||||
|
ManifestNodeEntry {
|
||||||
|
name: "*".to_string(),
|
||||||
|
id: (&*client_module_id).into(),
|
||||||
|
chunks: client_chunks_paths.clone(),
|
||||||
|
// TODO(WEB-434)
|
||||||
|
r#async: false,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
ssr_manifest_node.module_exports.insert(
|
||||||
|
"*".to_string(),
|
||||||
|
ManifestNodeEntry {
|
||||||
|
name: "*".to_string(),
|
||||||
|
id: (&*ssr_module_id).into(),
|
||||||
|
chunks: ssr_chunks_paths.clone(),
|
||||||
|
// TODO(WEB-434)
|
||||||
|
r#async: false,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
entry_manifest
|
||||||
|
.ssr_module_mapping
|
||||||
|
.insert((&*client_module_id).into(), ssr_manifest_node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let client_reference_manifest_json = serde_json::to_string(&entry_manifest).unwrap();
|
||||||
|
|
||||||
|
Ok(Vc::upcast(RawOutput::new(Vc::upcast(VirtualSource::new(
|
||||||
|
node_root.join(format!(
|
||||||
|
"server/app/{entry_name}_client-reference-manifest.js",
|
||||||
|
)),
|
||||||
|
AssetContent::file(
|
||||||
|
File::from(formatdoc! {
|
||||||
|
r#"
|
||||||
|
globalThis.__RSC_MANIFEST = globalThis.__RSC_MANIFEST || {{}};
|
||||||
|
globalThis.__RSC_MANIFEST[{entry_name}] = {manifest}
|
||||||
|
"#,
|
||||||
|
entry_name = StringifyJs(&entry_name),
|
||||||
|
manifest = StringifyJs(&client_reference_manifest_json)
|
||||||
|
})
|
||||||
|
.into(),
|
||||||
|
),
|
||||||
|
)))))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<&TurbopackModuleId> for ModuleId {
|
||||||
|
fn from(module_id: &TurbopackModuleId) -> Self {
|
||||||
|
match module_id {
|
||||||
|
TurbopackModuleId::String(string) => ModuleId::String(string.clone()),
|
||||||
|
TurbopackModuleId::Number(number) => ModuleId::Number(*number as _),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// See next.js/packages/next/src/lib/client-reference.ts
|
||||||
|
pub fn get_client_reference_module_key(server_path: &str, export_name: &str) -> String {
|
||||||
|
if export_name == "*" {
|
||||||
|
server_path.to_string()
|
||||||
|
} else {
|
||||||
|
format!("{}#{}", server_path, export_name)
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,10 +1,13 @@
|
||||||
//! Type definitions for the Next.js manifest formats.
|
//! Type definitions for the Next.js manifest formats.
|
||||||
|
|
||||||
|
pub(crate) mod client_reference_manifest;
|
||||||
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use next_core::next_config::Rewrites;
|
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
|
||||||
|
use crate::next_config::Rewrites;
|
||||||
|
|
||||||
#[derive(Serialize, Default, Debug)]
|
#[derive(Serialize, Default, Debug)]
|
||||||
pub struct PagesManifest {
|
pub struct PagesManifest {
|
||||||
#[serde(flatten)]
|
#[serde(flatten)]
|
|
@ -24,7 +24,7 @@ use indexmap::IndexMap;
|
||||||
use next_core::{
|
use next_core::{
|
||||||
app_structure::find_app_dir_if_enabled,
|
app_structure::find_app_dir_if_enabled,
|
||||||
create_app_source, create_page_source, create_web_entry_source,
|
create_app_source, create_page_source, create_web_entry_source,
|
||||||
manifest::DevManifestContentSource,
|
dev_manifest::DevManifestContentSource,
|
||||||
mode::NextMode,
|
mode::NextMode,
|
||||||
next_client::{get_client_chunking_context, get_client_compile_time_info},
|
next_client::{get_client_chunking_context, get_client_compile_time_info},
|
||||||
next_config::{load_next_config, load_rewrites},
|
next_config::{load_next_config, load_rewrites},
|
||||||
|
|
|
@ -265,6 +265,12 @@ const nextDev: CliCommand = async (argv) => {
|
||||||
Log.info(written)
|
Log.info(written)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
case 'app-page': {
|
||||||
|
Log.info(`writing ${pathname} to disk`)
|
||||||
|
const written = await route.rscEndpoint.writeToDisk()
|
||||||
|
Log.info(written)
|
||||||
|
break
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
Log.info(`skipping ${pathname} (${route.type})`)
|
Log.info(`skipping ${pathname} (${route.type})`)
|
||||||
break
|
break
|
||||||
|
|
|
@ -992,8 +992,8 @@ importers:
|
||||||
'@types/react': 18.2.7
|
'@types/react': 18.2.7
|
||||||
'@types/react-dom': 18.2.4
|
'@types/react-dom': 18.2.4
|
||||||
'@vercel/ncc': ^0.36.0
|
'@vercel/ncc': ^0.36.0
|
||||||
'@vercel/turbopack-ecmascript-runtime': https://gitpkg-fork.vercel.sh/vercel/turbo/crates/turbopack-ecmascript-runtime/js?turbopack-230716.2
|
'@vercel/turbopack-ecmascript-runtime': https://gitpkg-fork.vercel.sh/vercel/turbo/crates/turbopack-ecmascript-runtime/js?turbopack-230717.2
|
||||||
'@vercel/turbopack-node': https://gitpkg-fork.vercel.sh/vercel/turbo/crates/turbopack-node/js?turbopack-230716.2
|
'@vercel/turbopack-node': https://gitpkg-fork.vercel.sh/vercel/turbo/crates/turbopack-node/js?turbopack-230717.2
|
||||||
anser: ^2.1.1
|
anser: ^2.1.1
|
||||||
css.escape: ^1.5.1
|
css.escape: ^1.5.1
|
||||||
find-up: ^6.3.0
|
find-up: ^6.3.0
|
||||||
|
@ -1005,8 +1005,8 @@ importers:
|
||||||
stacktrace-parser: ^0.1.10
|
stacktrace-parser: ^0.1.10
|
||||||
strip-ansi: ^7.0.1
|
strip-ansi: ^7.0.1
|
||||||
dependencies:
|
dependencies:
|
||||||
'@vercel/turbopack-ecmascript-runtime': '@gitpkg-fork.vercel.sh/vercel/turbo/crates/turbopack-ecmascript-runtime/js?turbopack-230716.2_react-refresh@0.12.0'
|
'@vercel/turbopack-ecmascript-runtime': '@gitpkg-fork.vercel.sh/vercel/turbo/crates/turbopack-ecmascript-runtime/js?turbopack-230717.2_react-refresh@0.12.0'
|
||||||
'@vercel/turbopack-node': '@gitpkg-fork.vercel.sh/vercel/turbo/crates/turbopack-node/js?turbopack-230716.2'
|
'@vercel/turbopack-node': '@gitpkg-fork.vercel.sh/vercel/turbo/crates/turbopack-node/js?turbopack-230717.2'
|
||||||
anser: 2.1.1
|
anser: 2.1.1
|
||||||
css.escape: 1.5.1
|
css.escape: 1.5.1
|
||||||
next: link:../../../../next
|
next: link:../../../../next
|
||||||
|
@ -25498,9 +25498,9 @@ packages:
|
||||||
/zwitch/2.0.4:
|
/zwitch/2.0.4:
|
||||||
resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==}
|
resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==}
|
||||||
|
|
||||||
'@gitpkg-fork.vercel.sh/vercel/turbo/crates/turbopack-ecmascript-runtime/js?turbopack-230716.2_react-refresh@0.12.0':
|
'@gitpkg-fork.vercel.sh/vercel/turbo/crates/turbopack-ecmascript-runtime/js?turbopack-230717.2_react-refresh@0.12.0':
|
||||||
resolution: {tarball: https://gitpkg-fork.vercel.sh/vercel/turbo/crates/turbopack-ecmascript-runtime/js?turbopack-230716.2}
|
resolution: {tarball: https://gitpkg-fork.vercel.sh/vercel/turbo/crates/turbopack-ecmascript-runtime/js?turbopack-230717.2}
|
||||||
id: '@gitpkg-fork.vercel.sh/vercel/turbo/crates/turbopack-ecmascript-runtime/js?turbopack-230716.2'
|
id: '@gitpkg-fork.vercel.sh/vercel/turbo/crates/turbopack-ecmascript-runtime/js?turbopack-230717.2'
|
||||||
name: '@vercel/turbopack-ecmascript-runtime'
|
name: '@vercel/turbopack-ecmascript-runtime'
|
||||||
version: 0.0.0
|
version: 0.0.0
|
||||||
dependencies:
|
dependencies:
|
||||||
|
@ -25511,8 +25511,8 @@ packages:
|
||||||
- webpack
|
- webpack
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
'@gitpkg-fork.vercel.sh/vercel/turbo/crates/turbopack-node/js?turbopack-230716.2':
|
'@gitpkg-fork.vercel.sh/vercel/turbo/crates/turbopack-node/js?turbopack-230717.2':
|
||||||
resolution: {tarball: https://gitpkg-fork.vercel.sh/vercel/turbo/crates/turbopack-node/js?turbopack-230716.2}
|
resolution: {tarball: https://gitpkg-fork.vercel.sh/vercel/turbo/crates/turbopack-node/js?turbopack-230717.2}
|
||||||
name: '@vercel/turbopack-node'
|
name: '@vercel/turbopack-node'
|
||||||
version: 0.0.0
|
version: 0.0.0
|
||||||
dependencies:
|
dependencies:
|
||||||
|
|
Loading…
Reference in a new issue