feat(next-core): apply rsc transform in turbopack (#59629)

### What?

Turbopack does not apply same transform for the react server components,
which makes missing lot of compilation error validation and custom
comments. PR refactors transform to be used in next-swc / turbopack
both, then apply it into turbopack.

There are still some of test cases are not passing, might need further
digging for the transform condition.


Closes PACK-2155

---------

Co-authored-by: Tim Neutkens <tim@timneutkens.nl>
This commit is contained in:
OJ Kwon 2024-01-05 07:14:06 -08:00 committed by GitHub
parent f60c609bdb
commit f641d9ccfc
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 449 additions and 266 deletions

222
Cargo.lock generated
View file

@ -521,9 +521,9 @@ dependencies = [
[[package]]
name = "binding_macros"
version = "0.61.9"
version = "0.61.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6d1716f24e94103e6cb4d0a267d80b3a572692cbdcd7969ff2212adbc340ea7"
checksum = "6f223044d1a486a04e27ae0012400169aeb9f6fba2e86f72537c1e827a2f8c1c"
dependencies = [
"anyhow",
"console_error_panic_hook",
@ -3445,6 +3445,7 @@ dependencies = [
"next-swc",
"next-transform-dynamic",
"next-transform-font",
"next-transform-react-server-components",
"next-transform-strip-page-exports",
"once_cell",
"qstring",
@ -3471,6 +3472,8 @@ dependencies = [
"hex",
"next-transform-dynamic",
"next-transform-font",
"next-transform-react-server-components",
"next-visitor-cjs-finder",
"once_cell",
"pathdiff",
"react_remove_properties",
@ -3535,6 +3538,18 @@ dependencies = [
"swc_core",
]
[[package]]
name = "next-transform-react-server-components"
version = "0.1.0"
dependencies = [
"anyhow",
"next-visitor-cjs-finder",
"regex",
"serde",
"serde_json",
"swc_core",
]
[[package]]
name = "next-transform-strip-page-exports"
version = "0.1.0"
@ -3545,6 +3560,13 @@ dependencies = [
"tracing",
]
[[package]]
name = "next-visitor-cjs-finder"
version = "0.1.0"
dependencies = [
"swc_core",
]
[[package]]
name = "node-file-trace"
version = "0.1.0"
@ -5258,9 +5280,9 @@ checksum = "ae1a47186c03a32177042e55dbc5fd5aee900b8e0069a8d70fba96a9375cd012"
[[package]]
name = "sha2"
version = "0.10.8"
version = "0.10.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8"
checksum = "82e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0"
dependencies = [
"cfg-if 1.0.0",
"cpufeatures",
@ -5728,9 +5750,9 @@ dependencies = [
[[package]]
name = "swc"
version = "0.270.10"
version = "0.270.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "05aaaaae20ffb7d640865597be257f4ace06ad8556cdf823ac721805cb5d654c"
checksum = "7a27aa57c85cbd942540fe5e50f5d665723a1666305506f0cf0daf423903e2a9"
dependencies = [
"anyhow",
"base64 0.21.4",
@ -5794,9 +5816,9 @@ dependencies = [
[[package]]
name = "swc_bundler"
version = "0.223.8"
version = "0.223.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "965299522027c285ac65b8e2419c1fab845e38c08d22e020dbb959afc77286f3"
checksum = "e912d8387fc8592465c081b2e6b8df89443117ae4ca5160f21e08d47d7d58d7a"
dependencies = [
"anyhow",
"crc",
@ -5873,9 +5895,9 @@ dependencies = [
[[package]]
name = "swc_compiler_base"
version = "0.4.8"
version = "0.4.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b2ebca7b430009d4557bf0f9b1d6653fe1adea0aa68a70555499d7b960ef3880"
checksum = "2b8a76c7c388f1db934d10ba7fd293ea69e6ed8bd031855b579e4794aff5af85"
dependencies = [
"anyhow",
"base64 0.21.4",
@ -5921,9 +5943,9 @@ dependencies = [
[[package]]
name = "swc_core"
version = "0.87.10"
version = "0.87.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6f0e1d5e08e79bea5f7dadd8d8fd023dd60fde1fbcc9c5c87c420b00483af758"
checksum = "455c32b15bcdf8cddd87ce4c5d51f89bc16dfb3e6e58959e1cead7634ab2e828"
dependencies = [
"binding_macros",
"swc",
@ -5962,9 +5984,9 @@ dependencies = [
[[package]]
name = "swc_css_ast"
version = "0.140.13"
version = "0.140.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec1b459dc890410ea18225d2879786247f1dbc2ddb95eb92cae9dd83c6193ed5"
checksum = "85eb09e34d7a6e1869897b4aa884c739c5f5320aea00b35b589d2e4391e47868"
dependencies = [
"is-macro",
"string_enum",
@ -5974,9 +5996,9 @@ dependencies = [
[[package]]
name = "swc_css_codegen"
version = "0.151.22"
version = "0.151.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b0abf66b951f31b7bc8e1877edbf64744bb1ccd38b271ca41a57e24b4c99956"
checksum = "5d292d3dbf611b6be21980919f8896852af40bbb0d430d6008f4283685137e64"
dependencies = [
"auto_impl",
"bitflags 2.4.0",
@ -6003,9 +6025,9 @@ dependencies = [
[[package]]
name = "swc_css_compat"
version = "0.27.23"
version = "0.27.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "61b846b7cfc13b28c5d43c0f9927e8ef0b01826da70ccbaee26487f13299c060"
checksum = "a544c80e5b481dab958e4bdd1286349b7583b1412e53993fbcf1aeb83d0e585e"
dependencies = [
"bitflags 2.4.0",
"once_cell",
@ -6020,9 +6042,9 @@ dependencies = [
[[package]]
name = "swc_css_minifier"
version = "0.116.22"
version = "0.116.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2a8a5b334be14e66a4ccdf98de4cac7065f901390cf5b761a873673ad251898"
checksum = "e9807dea905a6c4696076ff642e507ecaf63e624ef20c55a303017d3e6f301e9"
dependencies = [
"serde",
"swc_atoms",
@ -6034,9 +6056,9 @@ dependencies = [
[[package]]
name = "swc_css_modules"
version = "0.29.25"
version = "0.29.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2585bd54215cbaa2102904c3ed0262d34c175cfd140c788aa5072e2c2432f745"
checksum = "caceeba805e5123dbbe9f4210bb28644ea026bdd7a6f407046c7b3c941573332"
dependencies = [
"rustc-hash",
"serde",
@ -6050,9 +6072,9 @@ dependencies = [
[[package]]
name = "swc_css_parser"
version = "0.150.21"
version = "0.150.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c788f5ca9a539504609fde165da45288a55fb3eb07fb2c54bd8df7794dcb072"
checksum = "9fb8221a52f2f50cd23c6b70fa024f4ef21a3dd737a67965292fdac49f391036"
dependencies = [
"lexical",
"serde",
@ -6063,9 +6085,9 @@ dependencies = [
[[package]]
name = "swc_css_prefixer"
version = "0.153.23"
version = "0.153.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c34762ca85e7136bfb83036467b91a296818471660da2955e5df0d1de14d3f4"
checksum = "74adc2822de64d5215ad253ce360dc39f99686dbb46840b6ae374aad69133cfa"
dependencies = [
"once_cell",
"preset_env_base",
@ -6080,9 +6102,9 @@ dependencies = [
[[package]]
name = "swc_css_utils"
version = "0.137.13"
version = "0.137.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c6b4b604827b202bcf644ced07ad897ae5cbb5fae62a8a3d154ebca73da06b0f"
checksum = "426952c65332d750820cc4cb2b8e21955d6315c57b30939e43def2c48f36c55f"
dependencies = [
"once_cell",
"serde",
@ -6095,9 +6117,9 @@ dependencies = [
[[package]]
name = "swc_css_visit"
version = "0.139.13"
version = "0.139.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "761dc5b0b95b7c950083519dda1f82246566f6682b3b21a009b1e0e20a6d693c"
checksum = "0653b91d85ef5415bfd7b205d03d7a4772ec8e324c980873523294bc2e827717"
dependencies = [
"serde",
"swc_atoms",
@ -6108,9 +6130,9 @@ dependencies = [
[[package]]
name = "swc_ecma_ast"
version = "0.110.15"
version = "0.110.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2aa3e4c43a071a747bf3e18a5423d47aab54048fdedab550d7f3c662127ba4d8"
checksum = "79401a45da704f4fb2552c5bf86ee2198e8636b121cb81f8036848a300edd53b"
dependencies = [
"bitflags 2.4.0",
"bytecheck",
@ -6128,9 +6150,9 @@ dependencies = [
[[package]]
name = "swc_ecma_codegen"
version = "0.146.48"
version = "0.146.54"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "86bb6d13035523d41a75ff9cdfd8802fac15fd0fd7e217306d9ae72f2ddc13f1"
checksum = "99b61ca275e3663238b71c4b5da8e6fb745bde9989ef37d94984dfc81fc6d009"
dependencies = [
"memchr",
"num-bigint",
@ -6159,9 +6181,9 @@ dependencies = [
[[package]]
name = "swc_ecma_compat_bugfixes"
version = "0.2.7"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57b38205191eaecddb2c3efe33dfedd6ee97e9cb9a155af7c3c722a7e8895b79"
checksum = "9a69ac870b965a458340c6a5a31059f8473093595a1f9efb169002f23bc05261"
dependencies = [
"swc_atoms",
"swc_common",
@ -6176,9 +6198,9 @@ dependencies = [
[[package]]
name = "swc_ecma_compat_common"
version = "0.2.2"
version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "33232ee8d61059c3359b8734efbaa9cfb6558c96f6a0d1a85cc06f9cf3d40261"
checksum = "8b0a57bd134c03dd545263ee41824a8cb06af1553016dccf8ac1ad8cbbb940c3"
dependencies = [
"swc_common",
"swc_ecma_ast",
@ -6189,9 +6211,9 @@ dependencies = [
[[package]]
name = "swc_ecma_compat_es2015"
version = "0.2.7"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2c8f000c0a0c344fb2eee695116aac050894ed3168be00bea7960dbc39a516fd"
checksum = "6189b89270bca5d3b103818a49c8decca0f9a63b4507f4f5301b052b0fb42d51"
dependencies = [
"arrayvec",
"indexmap 2.0.0",
@ -6215,9 +6237,9 @@ dependencies = [
[[package]]
name = "swc_ecma_compat_es2016"
version = "0.2.5"
version = "0.2.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ec5acfe5730f317bbf249e9fb92bc926b14f5cb6fda9a58c7ceed30f4f3db32"
checksum = "0708c1ae05f82d4e19da2f02a5b093e4e50d581e9bfac527f4aa7693bd791cf7"
dependencies = [
"swc_atoms",
"swc_common",
@ -6232,9 +6254,9 @@ dependencies = [
[[package]]
name = "swc_ecma_compat_es2017"
version = "0.2.5"
version = "0.2.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "92c892ea977c52478805eb387e8abd87180a99c7275b64428a683fa40300d1ac"
checksum = "e3701ee2c0321f79258a2acc3633b875af7770cd0173e17a0615d9e707ba32ac"
dependencies = [
"serde",
"swc_atoms",
@ -6250,9 +6272,9 @@ dependencies = [
[[package]]
name = "swc_ecma_compat_es2018"
version = "0.2.6"
version = "0.2.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f7fc343bd82c7d0b457da37b7c90a6f5bb207b4f29f080f34d5509cbc7ee0c71"
checksum = "def1e23336a20ca46d297685c2f5c60703eb2d7aea0b8996fefa577be3fad508"
dependencies = [
"serde",
"swc_atoms",
@ -6269,9 +6291,9 @@ dependencies = [
[[package]]
name = "swc_ecma_compat_es2019"
version = "0.2.5"
version = "0.2.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "db7925f1535272e89fa7688471505fdcf84c07686b8f543f2ff7c7a7c4dffb7a"
checksum = "72dd4288e3dfbba53a72410daf190d84d7601f91300e6c524ddea1f0708f2495"
dependencies = [
"swc_atoms",
"swc_common",
@ -6285,9 +6307,9 @@ dependencies = [
[[package]]
name = "swc_ecma_compat_es2020"
version = "0.2.6"
version = "0.2.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f7a049c2b8775dfafe55504810b5619d293b80e3afcf6fc58727d73095d89290"
checksum = "f654fe803d73320c723ba25e88b4b561fd1d53ad59ad8622f209fe03f6849b3b"
dependencies = [
"serde",
"swc_atoms",
@ -6303,9 +6325,9 @@ dependencies = [
[[package]]
name = "swc_ecma_compat_es2021"
version = "0.2.5"
version = "0.2.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3e675286ffd4be6d3d038593f3858ab57f761eec4975b3e271c93f3ae1d16b5e"
checksum = "9a33089b3b121acadc052ca636905c1dd465db3cc94fa456c26eacc65d5074db"
dependencies = [
"swc_atoms",
"swc_common",
@ -6319,9 +6341,9 @@ dependencies = [
[[package]]
name = "swc_ecma_compat_es2022"
version = "0.2.6"
version = "0.2.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5141124b7edbe46da07195a7799dbbdb33815a6e63c4afde9ffeac42e5280b50"
checksum = "ebe2a334c1ed213b0a58adb09518c63c63229afad705e5ab027e2fd0f3ff20bd"
dependencies = [
"swc_atoms",
"swc_common",
@ -6338,9 +6360,9 @@ dependencies = [
[[package]]
name = "swc_ecma_compat_es3"
version = "0.2.5"
version = "0.2.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1804166f985561cf8f0f9975ac36a350510910acc224b7c2d437b2f6d15bea2e"
checksum = "5b2f3ac54636b7690f17adc9430318d83bf8423635ca848bbb9f9c045e01e377"
dependencies = [
"swc_common",
"swc_ecma_ast",
@ -6353,9 +6375,9 @@ dependencies = [
[[package]]
name = "swc_ecma_ext_transforms"
version = "0.111.1"
version = "0.111.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "467c0692a8a1a68eed822db03127ecef888eaa8fae9faed510d1b2a8873b8215"
checksum = "4e728d14119048a95e023c3c5c0ad5ddddb1f405bfef3bd55f81dc5fc3c9e95a"
dependencies = [
"phf 0.11.2",
"swc_atoms",
@ -6367,9 +6389,9 @@ dependencies = [
[[package]]
name = "swc_ecma_lints"
version = "0.90.5"
version = "0.90.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "695bb91f19bdd0b65d675ebd73895d86b7e0ab4ca1cb81917cc803c468ee45b4"
checksum = "5afe579c82fe80a24e8c815fa19e7f1126c8114db0985f211c985d5b4db4137e"
dependencies = [
"auto_impl",
"dashmap",
@ -6408,9 +6430,9 @@ dependencies = [
[[package]]
name = "swc_ecma_minifier"
version = "0.190.8"
version = "0.190.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cc73ee27d9a4bcae2f8791913da8bcd610274dcb28e1e17a5fe38d1cb3137496"
checksum = "cdd196fa7d01ddd4eaa935f0ddd12854df57db21243aebde9169882d22d381f3"
dependencies = [
"arrayvec",
"indexmap 2.0.0",
@ -6443,9 +6465,9 @@ dependencies = [
[[package]]
name = "swc_ecma_parser"
version = "0.141.34"
version = "0.141.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2a67621d078321fb09e73ebe3084da09c352a5dfc1075c6ee833dea2c0209529"
checksum = "c4d17401dd95048a6a62b777d533c0999dabdd531ef9d667e22f8ae2a2a0d294"
dependencies = [
"either",
"new_debug_unreachable",
@ -6465,9 +6487,9 @@ dependencies = [
[[package]]
name = "swc_ecma_preset_env"
version = "0.204.7"
version = "0.204.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eda37d5dc19f9462efd4eb0f96f5d32e7258035574c2fb12298a5406d19afaf9"
checksum = "94556b1404aa1c8e9f22312fe83a11b5c882b0122557daae1187826575162627"
dependencies = [
"anyhow",
"dashmap",
@ -6490,9 +6512,9 @@ dependencies = [
[[package]]
name = "swc_ecma_quote_macros"
version = "0.52.34"
version = "0.52.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4642b332ceef54ca1420a748d184f9728670fd548726fa6d3f46b01396fe3551"
checksum = "d2bd72fda3eb232e08ac6ce9766edb59791dab5f588377c151a1da6c1862b734"
dependencies = [
"anyhow",
"proc-macro2",
@ -6520,9 +6542,9 @@ dependencies = [
[[package]]
name = "swc_ecma_transforms"
version = "0.227.7"
version = "0.227.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cbbbb5ed23c63d99f4290ccaa5715abfaf7c12f0f3ab07423663a5fcb185fe5d"
checksum = "b319ba24f6311afa72c5d7e81f06f52b1cd9ad4debf0524eac599b7640b9039a"
dependencies = [
"swc_atoms",
"swc_common",
@ -6540,9 +6562,9 @@ dependencies = [
[[package]]
name = "swc_ecma_transforms_base"
version = "0.135.5"
version = "0.135.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2592b26fc593f5917935d0fe79524e458837de4049b10afb05e3418461dc68a9"
checksum = "6d4ab26ec124b03e47f54d4daade8e9a9dcd66d3a4ca3cd47045f138d267a60e"
dependencies = [
"better_scoped_tls",
"bitflags 2.4.0",
@ -6564,9 +6586,9 @@ dependencies = [
[[package]]
name = "swc_ecma_transforms_classes"
version = "0.124.5"
version = "0.124.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c560c5d364140754675ecd9404d8f5ea84df354d39ed616d6fd23a15874e2194"
checksum = "9fe4376c024fa04394cafb8faecafb4623722b92dbbe46532258cc0a6b569d9c"
dependencies = [
"swc_atoms",
"swc_common",
@ -6578,9 +6600,9 @@ dependencies = [
[[package]]
name = "swc_ecma_transforms_compat"
version = "0.161.7"
version = "0.161.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f86e7531ce193c3ac1babea420db10e8ddefdf8c88c8619b245228c8f4cac7d"
checksum = "93a7192ebd94fa4454114ff79513000260ac583d3b80067d9037daa119f318df"
dependencies = [
"arrayvec",
"indexmap 2.0.0",
@ -6627,9 +6649,9 @@ dependencies = [
[[package]]
name = "swc_ecma_transforms_module"
version = "0.178.7"
version = "0.178.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "997191873260eb18707f8e5de3c6dc20d4a5e67311532fe4ad2e6bfdadc655ba"
checksum = "fc1ba85cf4620c7690eb67f00bf2b1efa0d88265bbbf8cea60dfc7aec59c3e99"
dependencies = [
"Inflector",
"anyhow",
@ -6654,9 +6676,9 @@ dependencies = [
[[package]]
name = "swc_ecma_transforms_optimization"
version = "0.196.7"
version = "0.196.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c489523b48c24d00906b148f59c24b3d07c35c00bf53233d69ef69b603631b13"
checksum = "eefef9f5a80afdbd4b517401dc053825d1ac0d95bb63f3ae92d2b335d8d7d4f8"
dependencies = [
"dashmap",
"indexmap 2.0.0",
@ -6679,9 +6701,9 @@ dependencies = [
[[package]]
name = "swc_ecma_transforms_proposal"
version = "0.169.7"
version = "0.169.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7854a2eb5953bb35e6db890dd5db6d50b436a489d1fb2a3d02b86187d07f84b5"
checksum = "86de99757fc31d8977f47c02a26e5c9a243cb63b03fe8aa8b36d79924b8fa29c"
dependencies = [
"either",
"rustc-hash",
@ -6699,9 +6721,9 @@ dependencies = [
[[package]]
name = "swc_ecma_transforms_react"
version = "0.181.7"
version = "0.181.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "574213391391a13cd02fafd6257cc970b71d66a2be823d1107546a1e829d71a2"
checksum = "9918e22caf1ea4a71085f5d818d6c0bf5c19d669cfb9d38f9fdc3da0496abdc7"
dependencies = [
"base64 0.21.4",
"dashmap",
@ -6724,9 +6746,9 @@ dependencies = [
[[package]]
name = "swc_ecma_transforms_testing"
version = "0.138.5"
version = "0.138.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e90f6f8f95556e05a3abc1d6725a9849bd6dafb2e6a2c67b42aa4c70227df2de"
checksum = "c9def5b4509c1764173a5cfce81d46d3d64ae479fbc7f1975ba3758dda4abc79"
dependencies = [
"ansi_term",
"anyhow",
@ -6750,9 +6772,9 @@ dependencies = [
[[package]]
name = "swc_ecma_transforms_typescript"
version = "0.186.7"
version = "0.186.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cdf0d2543127998a3be5cc254955e8eb67b93f4048d2f3afda0780f6f3784403"
checksum = "e1d1495c969ffdc224384f1fb73646b9c1b170779f20fdb984518deb054aa522"
dependencies = [
"ryu-js",
"serde",
@ -6767,9 +6789,9 @@ dependencies = [
[[package]]
name = "swc_ecma_usage_analyzer"
version = "0.21.2"
version = "0.21.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "645c7788fc819b3f38c48fd4464d8e98bf041ff58cdc8299243ed62315ce2100"
checksum = "2bf6ae5dd022ac6f39034896dd94eaeb590bf1fc6ab6e4f302fc9cdd8569e9b7"
dependencies = [
"indexmap 2.0.0",
"rustc-hash",
@ -6784,9 +6806,9 @@ dependencies = [
[[package]]
name = "swc_ecma_utils"
version = "0.125.1"
version = "0.125.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3cfe59ddbeeba9015fe8fdb82d3141d939e09b70350aa064e183a9a7bc2f36bf"
checksum = "7cead1083e46b0f072a82938f16d366014468f7510350957765bb4d013496890"
dependencies = [
"indexmap 2.0.0",
"num_cpus",
@ -6803,9 +6825,9 @@ dependencies = [
[[package]]
name = "swc_ecma_visit"
version = "0.96.15"
version = "0.96.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a823435d7b3d909391499c1d944be52fb9c6c59d6b5020367a511dfa1b1a3ecd"
checksum = "a1d0100c383fb08b6f34911ab6f925950416a5d14404c1cd520d59fb8dfbb3bf"
dependencies = [
"num-bigint",
"serde",
@ -6938,9 +6960,9 @@ dependencies = [
[[package]]
name = "swc_plugin_proxy"
version = "0.39.15"
version = "0.39.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2de6bfd049cad7723e8298cea8bf4f9ee4851a142f83fe935846887ead28c53d"
checksum = "9f00d9e79d36925854ce4de73acf397a6882a0dccb5b248d1ec48202ac3f72ad"
dependencies = [
"better_scoped_tls",
"rkyv",
@ -6952,9 +6974,9 @@ dependencies = [
[[package]]
name = "swc_plugin_runner"
version = "0.104.38"
version = "0.104.41"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dce10d3783b7792f8f06f8a9cfdd4f5a0ead041dd9fb05b78d0e74741bd1619e"
checksum = "26ed41b8a0e1a6afa4bca94c7e78329cccdce9271ec44cd3c4d67d097ce6c03f"
dependencies = [
"anyhow",
"enumset",
@ -7401,9 +7423,9 @@ dependencies = [
[[package]]
name = "tokio-stream"
version = "0.1.14"
version = "0.1.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "397c988d37662c7dda6d2208364a706264bf3d6138b11d436cbac0ad38832842"
checksum = "8fb52b74f05dbf495a8fba459fdc331812b96aa086d9eb78101fa0d4569c3313"
dependencies = [
"futures-core",
"pin-project-lite",

View file

@ -12,6 +12,8 @@ members = [
"packages/next-swc/crates/next-transform-font",
"packages/next-swc/crates/next-transform-dynamic",
"packages/next-swc/crates/next-transform-strip-page-exports",
"packages/next-swc/crates/next-transform-react-server-components",
"packages/next-swc/crates/next-visitor-cjs-finder",
]
[workspace.lints.clippy]
@ -34,6 +36,8 @@ next-swc = { path = "packages/next-swc/crates/core" }
next-transform-font = { path = "packages/next-swc/crates/next-transform-font" }
next-transform-dynamic = { path = "packages/next-swc/crates/next-transform-dynamic" }
next-transform-strip-page-exports = { path = "packages/next-swc/crates/next-transform-strip-page-exports" }
next-transform-react-server-components = { path = "packages/next-swc/crates/next-transform-react-server-components" }
next-visitor-cjs-finder = { path = "packages/next-swc/crates/next-visitor-cjs-finder" }
# SWC crates
swc_core = { version = "0.87.10", features = [

View file

@ -26,8 +26,10 @@ serde_json = "1"
sha1 = "0.10.1"
tracing = { version = "0.1.37" }
next-visitor-cjs-finder = { workspace = true }
next-transform-dynamic = { workspace = true }
next-transform-font = { workspace = true }
next-transform-react-server-components = { workspace = true }
turbopack-binding = { workspace = true, features = [
"__swc_core",

View file

@ -34,11 +34,11 @@ DEALINGS IN THE SOFTWARE.
use std::{cell::RefCell, path::PathBuf, rc::Rc, sync::Arc};
use auto_cjs::contains_cjs;
use either::Either;
use fxhash::FxHashSet;
use next_transform_dynamic::{next_dynamic, NextDynamicMode};
use next_transform_font::next_font_loaders;
use next_visitor_cjs_finder::contains_cjs;
use serde::Deserialize;
use turbopack_binding::swc::{
core::{
@ -56,7 +56,6 @@ use turbopack_binding::swc::{
};
pub mod amp_attributes;
mod auto_cjs;
pub mod cjs_optimizer;
pub mod disallow_re_export_all_in_page;
mod import_analyzer;
@ -66,7 +65,6 @@ pub mod optimize_barrel;
pub mod optimize_server_react;
pub mod page_config;
pub mod pure;
pub mod react_server_components;
pub mod server_actions;
pub mod shake_exports;
@ -101,7 +99,7 @@ pub struct TransformOptions {
pub prefer_esm: bool,
#[serde(default)]
pub server_components: Option<react_server_components::Config>,
pub server_components: Option<next_transform_react_server_components::Config>,
#[serde(default)]
pub styled_jsx: Option<turbopack_binding::swc::custom_transform::styled_jsx::visitor::Config>,
@ -194,7 +192,7 @@ where
disallow_re_export_all_in_page::disallow_re_export_all_in_page(opts.is_page_file),
match &opts.server_components {
Some(config) if config.truthy() =>
Either::Left(react_server_components::server_components(
Either::Left(next_transform_react_server_components::server_components(
file.name.clone(),
config.clone(),
comments.clone(),
@ -236,7 +234,7 @@ where
Some(config) if config.truthy() => match config {
// Always enable the Server Components mode for both
// server and client layers.
react_server_components::Config::WithOptions(config) => config.is_react_server_layer,
next_transform_react_server_components::Config::WithOptions(config) => config.is_react_server_layer,
_ => false,
},
_ => false,

View file

@ -63,6 +63,7 @@ turbo-tasks-fs = { workspace = true }
next-transform-strip-page-exports = { workspace = true }
next-transform-font = { workspace = true }
next-transform-dynamic = { workspace = true }
next-transform-react-server-components = { workspace = true }
swc_core = { workspace = true, features = [
"ecma_ast",

View file

@ -11,7 +11,9 @@ use crate::{
next_shared::transforms::{
get_next_dynamic_transform_rule, get_next_font_transform_rule, get_next_image_rule,
get_next_modularize_imports_rule, get_next_pages_transforms_rule,
get_server_actions_transform_rule, server_actions::ActionsTransform,
get_server_actions_transform_rule,
next_react_server_components::get_next_react_server_components_transform_rule,
server_actions::ActionsTransform,
},
};
@ -60,6 +62,11 @@ pub async fn get_next_server_transforms_rules(
ActionsTransform::Server,
mdx_rs,
));
rules.push(get_next_react_server_components_transform_rule(
true, mdx_rs,
));
if let Some(client_transition) = client_transition {
rules.push(get_next_css_client_reference_transforms_rule(
client_transition,

View file

@ -2,6 +2,7 @@ pub(crate) mod emotion;
pub(crate) mod modularize_imports;
pub(crate) mod next_dynamic;
pub(crate) mod next_font;
pub(crate) mod next_react_server_components;
pub(crate) mod next_strip_page_exports;
pub(crate) mod relay;
pub(crate) mod server_actions;

View file

@ -0,0 +1,62 @@
use std::path::PathBuf;
use anyhow::Result;
use async_trait::async_trait;
use next_transform_react_server_components::{server_components, Config, Options};
use swc_core::{
common::{util::take::Take, FileName},
ecma::{
ast::{Module, Program},
visit::FoldWith,
},
};
use turbo_tasks::Vc;
use turbopack_binding::turbopack::{
ecmascript::{CustomTransformer, EcmascriptInputTransform, TransformContext},
turbopack::module_options::{ModuleRule, ModuleRuleEffect},
};
use super::module_rule_match_js_no_url;
/// Returns a rule which applies the Next.js react server components transform.
pub fn get_next_react_server_components_transform_rule(
is_react_server_layer: bool,
enable_mdx_rs: bool,
) -> ModuleRule {
let transformer =
EcmascriptInputTransform::Plugin(Vc::cell(Box::new(NextJsReactServerComponents {
is_react_server_layer,
}) as _));
ModuleRule::new(
module_rule_match_js_no_url(enable_mdx_rs),
vec![ModuleRuleEffect::AddEcmascriptTransforms(Vc::cell(vec![
transformer,
]))],
)
}
#[derive(Debug)]
struct NextJsReactServerComponents {
is_react_server_layer: bool,
}
#[async_trait]
impl CustomTransformer for NextJsReactServerComponents {
async fn transform(&self, program: &mut Program, ctx: &TransformContext<'_>) -> Result<()> {
let p = std::mem::replace(program, Program::Module(Module::dummy()));
let mut visitor = server_components(
FileName::Custom(ctx.file_path_str.to_string()),
Config::WithOptions(Options {
is_react_server_layer: self.is_react_server_layer,
}),
ctx.comments,
Some(PathBuf::from(ctx.file_path.parent().await?.path.clone())),
);
*program = p.fold_with(&mut visitor);
Ok(())
}
}

View file

@ -0,0 +1,21 @@
[package]
name = "next-transform-react-server-components"
version = "0.1.0"
description = "TBD"
license = "MPL-2.0"
edition = "2021"
[lib]
bench = false
[lints]
workspace = true
[dependencies]
serde = { workspace = true }
serde_json = { workspace = true, features = ["preserve_order"] }
regex = "1.5"
anyhow = { workspace = true }
swc_core = { workspace = true }
next-visitor-cjs-finder = { workspace = true }

View file

@ -1,8 +1,11 @@
#![feature(arbitrary_self_types)]
use std::{collections::HashMap, path::PathBuf};
use next_visitor_cjs_finder::contains_cjs;
use regex::Regex;
use serde::Deserialize;
use turbopack_binding::swc::core::{
use swc_core::{
common::{
comments::{Comment, CommentKind, Comments},
errors::HANDLER,
@ -16,8 +19,6 @@ use turbopack_binding::swc::core::{
},
};
use crate::auto_cjs::contains_cjs;
#[derive(Clone, Debug, Deserialize)]
#[serde(untagged)]
pub enum Config {
@ -57,6 +58,102 @@ struct ModuleImports {
specifiers: Vec<(JsWord, Span)>,
}
enum RSCErrorKind {
/// When `use client` and `use server` are in the same file.
/// It's not possible to have both directives in the same file.
RedundantDirectives(Span),
NextRscErrServerImport((String, Span)),
NextRscErrClientImport((String, Span)),
NextRscErrClientDirective(Span),
NextRscErrReactApi((String, Span)),
NextRscErrErrorFileServerComponent(Span),
NextRscErrClientMetadataExport((String, Span)),
NextRscErrConflictMetadataExport(Span),
NextRscErrInvalidApi((String, Span)),
}
impl<C: Comments> ReactServerComponents<C> {
/// Consolidated place to parse, generate error messages for the RSC parsing
/// errors.
fn report_error(&self, error_kind: RSCErrorKind) {
let (msg, span) = match error_kind {
RSCErrorKind::RedundantDirectives(span) => (
"It's not possible to have both `use client` and `use server` directives in the \
same file."
.to_string(),
span,
),
RSCErrorKind::NextRscErrClientDirective(span) => (
"The \"use client\" directive must be placed before other expressions. Move it to \
the top of the file to resolve this issue."
.to_string(),
span,
),
RSCErrorKind::NextRscErrServerImport((source, span)) => {
let msg = match source.as_str() {
// If importing "react-dom/server", we should show a different error.
"react-dom/server" => "You're importing a component that imports react-dom/server. To fix it, render or return the content directly as a Server Component instead for perf and security.\nLearn more: https://nextjs.org/docs/getting-started/react-essentials".to_string(),
// If importing "next/router", we should tell them to use "next/navigation".
"next/router" => r#"You have a Server Component that imports next/router. Use next/navigation instead.\nLearn more: https://nextjs.org/docs/app/api-reference/functions/use-router"#.to_string(),
_ => format!(r#"You're importing a component that imports {}. It only works in a Client Component but none of its parents are marked with "use client", so they're Server Components by default.\nLearn more: https://nextjs.org/docs/getting-started/react-essentials\n\n"#, source)
};
(msg, span)
}
RSCErrorKind::NextRscErrClientImport((source, span)) => {
// [NOTE]: in turbopack currently only type of AppRsc runs this transform,
// so it won't hit pages_dir case
let is_app_dir = self
.app_dir
.as_ref()
.map(|app_dir| {
if let Some(app_dir) = app_dir.as_os_str().to_str() {
self.filepath.starts_with(app_dir)
} else {
false
}
})
.unwrap_or_default();
let msg = if !is_app_dir {
format!("You're importing a component that needs {}. That only works in a Server Component which is not supported in the pages/ directory. Read more: https://nextjs.org/docs/getting-started/react-essentials#server-components\n\n", source)
} else {
format!("You're importing a component that needs {}. That only works in a Server Component but one of its parents is marked with \"use client\", so it's a Client Component.\nLearn more: https://nextjs.org/docs/getting-started/react-essentials\n\n", source)
};
(msg, span)
}
RSCErrorKind::NextRscErrReactApi((source, span)) => {
let msg = if source == "Component" {
"Youre importing a class component. It only works in a Client Component but none of its parents are marked with \"use client\", so they're Server Components by default.\nLearn more: https://nextjs.org/docs/getting-started/react-essentials#client-components\n\n".to_string()
} else {
format!("You're importing a component that needs {}. It only works in a Client Component but none of its parents are marked with \"use client\", so they're Server Components by default.\nLearn more: https://nextjs.org/docs/getting-started/react-essentials\n\n", source)
};
(msg,span)
},
RSCErrorKind::NextRscErrErrorFileServerComponent(span) => {
(
format!("{} must be a Client Component. Add the \"use client\" directive the top of the file to resolve this issue.\nLearn more: https://nextjs.org/docs/getting-started/react-essentials#client-components\n\n", self.filepath),
span
)
},
RSCErrorKind::NextRscErrClientMetadataExport((source, span)) => {
(format!("You are attempting to export \"{}\" from a component marked with \"use client\", which is disallowed. Either remove the export, or the \"use client\" directive. Read more: https://nextjs.org/docs/getting-started/react-essentials#the-use-client-directive\n\n", source), span)
},
RSCErrorKind::NextRscErrConflictMetadataExport(span) => (
"\"metadata\" and \"generateMetadata\" cannot be exported at the same time, please keep one of them. Read more: https://nextjs.org/docs/app/api-reference/file-conventions/metadata\n\n".to_string(),
span
),
//NEXT_RSC_ERR_INVALID_API
RSCErrorKind::NextRscErrInvalidApi((source, span)) => (
format!("\"{}\" is not supported in app/. Read more: https://nextjs.org/docs/app/building-your-application/data-fetching\n\n", source), span
),
};
HANDLER.with(|handler| handler.struct_span_err(span, msg.as_str()).emit())
}
}
impl<C: Comments> VisitMut for ReactServerComponents<C> {
noop_visit_mut_type!();
@ -106,19 +203,6 @@ impl<C: Comments> ReactServerComponents<C> {
let mut is_client_entry = false;
let mut is_action_file = false;
fn panic_both_directives(span: Span) {
// It's not possible to have both directives in the same file.
HANDLER.with(|handler| {
handler
.struct_span_err(
span,
"It's not possible to have both `use client` and `use server` directives \
in the same file.",
)
.emit()
})
}
let _ = &module.body.retain(|item| {
match item {
ModuleItem::Stmt(stmt) => {
@ -136,17 +220,18 @@ impl<C: Comments> ReactServerComponents<C> {
is_client_entry = true;
if is_action_file {
panic_both_directives(expr_stmt.span)
self.report_error(
RSCErrorKind::RedundantDirectives(
expr_stmt.span,
),
);
}
} else {
HANDLER.with(|handler| {
handler
.struct_span_err(
expr_stmt.span,
"NEXT_RSC_ERR_CLIENT_DIRECTIVE",
)
.emit()
})
self.report_error(
RSCErrorKind::NextRscErrClientDirective(
expr_stmt.span,
),
);
}
// Remove the directive.
@ -155,7 +240,9 @@ impl<C: Comments> ReactServerComponents<C> {
is_action_file = true;
if is_client_entry {
panic_both_directives(expr_stmt.span)
self.report_error(RSCErrorKind::RedundantDirectives(
expr_stmt.span,
));
}
}
}
@ -166,14 +253,11 @@ impl<C: Comments> ReactServerComponents<C> {
finished_directives = true;
if let Expr::Lit(Lit::Str(Str { value, .. })) = &**expr {
if &**value == "use client" {
HANDLER.with(|handler| {
handler
.struct_span_err(
expr_stmt.span,
"NEXT_RSC_ERR_CLIENT_DIRECTIVE_PAREN",
)
.emit()
})
self.report_error(
RSCErrorKind::NextRscErrClientDirective(
expr_stmt.span,
),
);
}
}
}
@ -350,40 +434,28 @@ impl<C: Comments> ReactServerComponents<C> {
for import in imports {
let source = import.source.0.clone();
if self.invalid_server_imports.contains(&source) {
HANDLER.with(|handler| {
handler
.struct_span_err(
import.source.1,
format!("NEXT_RSC_ERR_SERVER_IMPORT: {}", source).as_str(),
)
.emit()
})
self.report_error(RSCErrorKind::NextRscErrServerImport((
source.to_string(),
import.source.1,
)));
}
if source == *"react" {
for specifier in &import.specifiers {
if self.invalid_server_react_apis.contains(&specifier.0) {
HANDLER.with(|handler| {
handler
.struct_span_err(
specifier.1,
format!("NEXT_RSC_ERR_REACT_API: {}", &specifier.0).as_str(),
)
.emit()
})
self.report_error(RSCErrorKind::NextRscErrReactApi((
specifier.0.to_string(),
specifier.1,
)));
}
}
}
if source == *"react-dom" {
for specifier in &import.specifiers {
if self.invalid_server_react_dom_apis.contains(&specifier.0) {
HANDLER.with(|handler| {
handler
.struct_span_err(
specifier.1,
format!("NEXT_RSC_ERR_REACT_API: {}", &specifier.0).as_str(),
)
.emit()
})
self.report_error(RSCErrorKind::NextRscErrReactApi((
specifier.0.to_string(),
specifier.1,
)));
}
}
}
@ -404,17 +476,13 @@ impl<C: Comments> ReactServerComponents<C> {
if let Some(app_dir) = &self.app_dir {
if let Some(app_dir) = app_dir.to_str() {
if self.filepath.starts_with(app_dir) {
HANDLER.with(|handler| {
let span = if let Some(first_item) = module.body.first() {
first_item.span()
} else {
module.span
};
let span = if let Some(first_item) = module.body.first() {
first_item.span()
} else {
module.span
};
handler
.struct_span_err(span, "NEXT_RSC_ERR_ERROR_FILE_SERVER_COMPONENT")
.emit()
})
self.report_error(RSCErrorKind::NextRscErrErrorFileServerComponent(span));
}
}
}
@ -428,14 +496,10 @@ impl<C: Comments> ReactServerComponents<C> {
for import in imports {
let source = import.source.0.clone();
if self.invalid_client_imports.contains(&source) {
HANDLER.with(|handler| {
handler
.struct_span_err(
import.source.1,
format!("NEXT_RSC_ERR_CLIENT_IMPORT: {}", source).as_str(),
)
.emit()
})
self.report_error(RSCErrorKind::NextRscErrClientImport((
source.to_string(),
import.source.1,
)));
}
}
}
@ -518,41 +582,25 @@ impl<C: Comments> ReactServerComponents<C> {
// Client entry can't export `generateMetadata` or `metadata`.
if is_client_entry {
if has_gm_export || has_metadata_export {
HANDLER.with(|handler| {
handler
.struct_span_err(
span,
format!(
"NEXT_RSC_ERR_CLIENT_METADATA_EXPORT: {}",
invalid_export_name
)
.as_str(),
)
.emit()
})
self.report_error(RSCErrorKind::NextRscErrClientMetadataExport((
invalid_export_name.clone(),
span,
)));
}
} else {
// Server entry can't export `generateMetadata` and `metadata` together.
if has_gm_export && has_metadata_export {
HANDLER.with(|handler| {
handler
.struct_span_err(span, "NEXT_RSC_ERR_CONFLICT_METADATA_EXPORT")
.emit()
})
self.report_error(RSCErrorKind::NextRscErrConflictMetadataExport(span));
}
}
// Assert `getServerSideProps` and `getStaticProps` exports.
if invalid_export_name == "getServerSideProps"
|| invalid_export_name == "getStaticProps"
{
HANDLER.with(|handler| {
handler
.struct_span_err(
span,
format!("NEXT_RSC_ERR_INVALID_API: {}", invalid_export_name).as_str(),
)
.emit()
})
self.report_error(RSCErrorKind::NextRscErrInvalidApi((
invalid_export_name.clone(),
span,
)));
}
}
}

View file

@ -0,0 +1,15 @@
[package]
name = "next-visitor-cjs-finder"
version = "0.1.0"
description = "TBD"
license = "MPL-2.0"
edition = "2021"
[lib]
bench = false
[lints]
workspace = true
[dependencies]
swc_core = { workspace = true }

View file

@ -1,9 +1,9 @@
use turbopack_binding::swc::core::ecma::{
use swc_core::ecma::{
ast::*,
visit::{Visit, VisitWith},
};
pub(crate) fn contains_cjs(m: &Module) -> bool {
pub fn contains_cjs(m: &Module) -> bool {
let mut v = CjsFinder::default();
m.visit_with(&mut v);
v.found && !v.is_esm

View file

@ -280,7 +280,7 @@ describe('Error overlay - RSC build errors', () => {
expect(await session.hasRedbox(true)).toBe(true)
expect(await session.getRedboxSource()).toInclude(
`You're importing a component that needs ${api}. It only works in a Client Component but none of its parents are marked with "use client", so they're Server Components by default.`
`You're importing a component that needs ${api}. It only works in a Client Component but none of its parents are marked with "use client", so they're Server Components`
)
await cleanup()
@ -348,25 +348,29 @@ describe('Error overlay - RSC build errors', () => {
)
expect(await session.hasRedbox(true)).toBe(true)
await check(() => session.getRedboxSource(), /must be a Client Component/)
await check(
() => session.getRedboxSource(),
/must be a Client \n| Component/
)
expect(
next.normalizeTestDirContent(await session.getRedboxSource())
).toMatchInlineSnapshot(
next.normalizeSnapshot(`
`
"./app/server-with-errors/error-file/error.js
ReactServerComponentsError:
./app/server-with-errors/error-file/error.js must be a Client Component. Add the "use client" directive the top of the file to resolve this issue.
Learn more: https://nextjs.org/docs/getting-started/react-essentials#client-components
Error:
x TEST_DIR/app/server-with-errors/error-file/error.js must be a Client Component. Add the "use client" directive the top
| of the file to resolve this issue.
| Learn more: https://nextjs.org/docs/getting-started/react-essentials#client-components
|
|
,-[TEST_DIR/app/server-with-errors/error-file/error.js:1:1]
1 | export default function Error() {}
: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
\`----
Import path:
Import trace for requested module:
./app/server-with-errors/error-file/error.js"
`)
`
)
await cleanup()

View file

@ -53,28 +53,27 @@ describe('Error Overlay for server components compiler errors in pages', () => {
() => session.getRedboxSource(),
/That only works in a Server Component/
)
expect(
next.normalizeTestDirContent(await session.getRedboxSource())
).toMatchInlineSnapshot(
next.normalizeSnapshot(`
"./components/Comp.js
ReactServerComponentsError:
You're importing a component that needs next/headers. That only works in a Server Component which is not supported in the pages/ directory. Read more: https://nextjs.org/docs/getting-started/react-essentials#server-components
expect(next.normalizeTestDirContent(await session.getRedboxSource()))
.toMatchInlineSnapshot(`
"./components/Comp.js
Error:
x You're importing a component that needs next/headers. That only works in a Server Component which is not supported in the pages/ directory. Read more: https://nextjs.org/docs/getting-started/
| react-essentials#server-components
|
|
,-[TEST_DIR/components/Comp.js:1:1]
1 | import { cookies } from 'next/headers'
: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2 |
3 | export default function Page() {
4 | return <p>hello world</p>
\`----
,-[TEST_DIR/components/Comp.js:1:1]
1 | import { cookies } from 'next/headers'
: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2 |
3 | export default function Page() {
4 | return <p>hello world</p>
\`----
Import trace for requested module:
./components/Comp.js
./pages/index.js"
`)
)
Import trace for requested module:
./components/Comp.js
./pages/index.js"
`)
await cleanup()
})
@ -85,7 +84,7 @@ describe('Error Overlay for server components compiler errors in pages', () => {
await next.patchFile(
'components/Comp.js',
outdent`
import 'server-only'
import 'server-only'
export default function Page() {
return 'hello world'
@ -98,28 +97,27 @@ describe('Error Overlay for server components compiler errors in pages', () => {
() => session.getRedboxSource(),
/That only works in a Server Component/
)
expect(
next.normalizeTestDirContent(await session.getRedboxSource())
).toMatchInlineSnapshot(
next.normalizeSnapshot(`
"./components/Comp.js
ReactServerComponentsError:
You're importing a component that needs server-only. That only works in a Server Component which is not supported in the pages/ directory. Read more: https://nextjs.org/docs/getting-started/react-essentials#server-components
expect(next.normalizeTestDirContent(await session.getRedboxSource()))
.toMatchInlineSnapshot(`
"./components/Comp.js
Error:
x You're importing a component that needs server-only. That only works in a Server Component which is not supported in the pages/ directory. Read more: https://nextjs.org/docs/getting-started/
| react-essentials#server-components
|
|
,-[TEST_DIR/components/Comp.js:1:1]
1 | import 'server-only'
: ^^^^^^^^^^^^^^^^^^^^
2 |
3 | export default function Page() {
4 | return 'hello world'
\`----
,-[TEST_DIR/components/Comp.js:1:1]
1 | import 'server-only'
: ^^^^^^^^^^^^^^^^^^^^
2 |
3 | export default function Page() {
4 | return 'hello world'
\`----
Import trace for requested module:
./components/Comp.js
./pages/index.js"
`)
)
Import trace for requested module:
./components/Comp.js
./pages/index.js"
`)
await cleanup()
})

View file

@ -1126,11 +1126,8 @@
"Error overlay - RSC build errors should error for invalid undefined module retuning from next dynamic",
"Error overlay - RSC build errors should error when page component export is not valid",
"Error overlay - RSC build errors should error when page component export is not valid on initial load",
"Error overlay - RSC build errors should freeze parent resolved metadata to avoid mutating in generateMetadata"
],
"failed": [
"Error overlay - RSC build errors should freeze parent resolved metadata to avoid mutating in generateMetadata",
"Error overlay - RSC build errors should allow to use and handle rsc poisoning client-only",
"Error overlay - RSC build errors should allow to use and handle rsc poisoning server-only",
"Error overlay - RSC build errors should error when Component from react is used in server component",
"Error overlay - RSC build errors should error when PureComponent from react is used in server component",
"Error overlay - RSC build errors should error when createContext from react is used in server component",
@ -1152,7 +1149,10 @@
"Error overlay - RSC build errors should error when useSyncExternalStore from react is used in server component",
"Error overlay - RSC build errors should error when useTransition from react is used in server component",
"Error overlay - RSC build errors should throw an error when \"Component\" is imported in server components",
"Error overlay - RSC build errors should throw an error when \"use client\" is on the top level but after other expressions",
"Error overlay - RSC build errors should throw an error when \"use client\" is on the top level but after other expressions"
],
"failed": [
"Error overlay - RSC build errors should allow to use and handle rsc poisoning server-only",
"Error overlay - RSC build errors should throw an error when error file is a server component",
"Error overlay - RSC build errors should throw an error when error file is a server component with empty error file",
"Error overlay - RSC build errors should throw an error when getServerSideProps is used",