Skip to content

Commit 64efdad

Browse files
authored
[Turbopack] fix import.meta.url in monorepo (vercel#72612)
### What? fixes the computation of `import.meta.url` inside of monorepos (when the root_path != project_path) ### How? We add a new argument to the ChunkingContext that represents the relative path from the output folder to the root of the monorepo. Since they are on different filesystems, we can't compute them from the values alone.
1 parent e79be05 commit 64efdad

File tree

164 files changed

+262
-135
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

164 files changed

+262
-135
lines changed

crates/next-api/src/project.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -647,6 +647,18 @@ impl Project {
647647
))
648648
}
649649

650+
#[turbo_tasks::function]
651+
pub async fn node_root_to_root_path(self: Vc<Self>) -> Result<Vc<RcStr>> {
652+
let this = self.await?;
653+
let output_root_to_root_path = self
654+
.project_path()
655+
.join(this.dist_dir.clone())
656+
.await?
657+
.get_relative_path_to(&*self.project_root_path().await?)
658+
.context("Project path need to be in root path")?;
659+
Ok(Vc::cell(output_root_to_root_path))
660+
}
661+
650662
#[turbo_tasks::function]
651663
pub async fn project_path(self: Vc<Self>) -> Result<Vc<FileSystemPath>> {
652664
let this = self.await?;
@@ -695,6 +707,7 @@ impl Project {
695707
NodeJsChunkingContext::builder(
696708
self.project_root_path().to_resolved().await?,
697709
node_root,
710+
self.node_root_to_root_path().to_resolved().await?,
698711
node_root,
699712
node_root.join("build/chunks".into()).to_resolved().await?,
700713
node_root.join("build/assets".into()).to_resolved().await?,
@@ -822,6 +835,7 @@ impl Project {
822835
get_client_chunking_context(
823836
self.project_root_path(),
824837
self.client_relative_path(),
838+
Vc::cell("/ROOT".into()),
825839
self.next_config().computed_asset_prefix(),
826840
self.client_compile_time_info().environment(),
827841
self.next_mode(),
@@ -840,6 +854,7 @@ impl Project {
840854
self.next_mode(),
841855
self.project_root_path(),
842856
self.node_root(),
857+
self.node_root_to_root_path(),
843858
self.client_relative_path(),
844859
self.next_config().computed_asset_prefix(),
845860
self.server_compile_time_info().environment(),
@@ -851,6 +866,7 @@ impl Project {
851866
self.next_mode(),
852867
self.project_root_path(),
853868
self.node_root(),
869+
self.node_root_to_root_path(),
854870
self.server_compile_time_info().environment(),
855871
self.module_id_strategy(),
856872
self.next_config().turbo_minify(self.next_mode()),
@@ -868,6 +884,7 @@ impl Project {
868884
self.next_mode(),
869885
self.project_root_path(),
870886
self.node_root(),
887+
self.node_root_to_root_path(),
871888
self.client_relative_path(),
872889
self.next_config().computed_asset_prefix(),
873890
self.edge_compile_time_info().environment(),
@@ -879,6 +896,7 @@ impl Project {
879896
self.next_mode(),
880897
self.project_root_path(),
881898
self.node_root(),
899+
self.node_root_to_root_path(),
882900
self.edge_compile_time_info().environment(),
883901
self.module_id_strategy(),
884902
self.next_config().turbo_minify(self.next_mode()),

crates/next-core/src/next_client/context.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -398,8 +398,9 @@ pub async fn get_client_module_options_context(
398398

399399
#[turbo_tasks::function]
400400
pub async fn get_client_chunking_context(
401-
project_path: ResolvedVc<FileSystemPath>,
401+
root_path: ResolvedVc<FileSystemPath>,
402402
client_root: ResolvedVc<FileSystemPath>,
403+
client_root_to_root_path: ResolvedVc<RcStr>,
403404
asset_prefix: ResolvedVc<Option<RcStr>>,
404405
environment: ResolvedVc<Environment>,
405406
mode: Vc<NextMode>,
@@ -408,8 +409,9 @@ pub async fn get_client_chunking_context(
408409
) -> Result<Vc<Box<dyn ChunkingContext>>> {
409410
let next_mode = mode.await?;
410411
let mut builder = BrowserChunkingContext::builder(
411-
project_path,
412+
root_path,
412413
client_root,
414+
client_root_to_root_path,
413415
client_root,
414416
client_root
415417
.join("static/chunks".into())

crates/next-core/src/next_edge/context.rs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -200,8 +200,9 @@ pub async fn get_edge_resolve_options_context(
200200
#[turbo_tasks::function]
201201
pub async fn get_edge_chunking_context_with_client_assets(
202202
mode: Vc<NextMode>,
203-
project_path: ResolvedVc<FileSystemPath>,
203+
root_path: ResolvedVc<FileSystemPath>,
204204
node_root: ResolvedVc<FileSystemPath>,
205+
output_root_to_root_path: ResolvedVc<RcStr>,
205206
client_root: ResolvedVc<FileSystemPath>,
206207
asset_prefix: ResolvedVc<Option<RcStr>>,
207208
environment: ResolvedVc<Environment>,
@@ -212,8 +213,9 @@ pub async fn get_edge_chunking_context_with_client_assets(
212213
let next_mode = mode.await?;
213214
Ok(Vc::upcast(
214215
BrowserChunkingContext::builder(
215-
project_path,
216+
root_path,
216217
output_root,
218+
output_root_to_root_path,
217219
client_root,
218220
output_root.join("chunks/ssr".into()).to_resolved().await?,
219221
client_root
@@ -237,8 +239,9 @@ pub async fn get_edge_chunking_context_with_client_assets(
237239
#[turbo_tasks::function]
238240
pub async fn get_edge_chunking_context(
239241
mode: Vc<NextMode>,
240-
project_path: ResolvedVc<FileSystemPath>,
242+
root_path: ResolvedVc<FileSystemPath>,
241243
node_root: ResolvedVc<FileSystemPath>,
244+
node_root_to_root_path: ResolvedVc<RcStr>,
242245
environment: ResolvedVc<Environment>,
243246
module_id_strategy: ResolvedVc<Box<dyn ModuleIdStrategy>>,
244247
turbo_minify: Vc<bool>,
@@ -247,8 +250,9 @@ pub async fn get_edge_chunking_context(
247250
let next_mode = mode.await?;
248251
Ok(Vc::upcast(
249252
BrowserChunkingContext::builder(
250-
project_path,
253+
root_path,
251254
output_root,
255+
node_root_to_root_path,
252256
output_root,
253257
output_root.join("chunks".into()).to_resolved().await?,
254258
output_root.join("assets".into()).to_resolved().await?,

crates/next-core/src/next_server/context.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -976,6 +976,7 @@ pub async fn get_server_chunking_context_with_client_assets(
976976
mode: Vc<NextMode>,
977977
root_path: ResolvedVc<FileSystemPath>,
978978
node_root: ResolvedVc<FileSystemPath>,
979+
node_root_to_root_path: ResolvedVc<RcStr>,
979980
client_root: ResolvedVc<FileSystemPath>,
980981
asset_prefix: ResolvedVc<Option<RcStr>>,
981982
environment: ResolvedVc<Environment>,
@@ -989,6 +990,7 @@ pub async fn get_server_chunking_context_with_client_assets(
989990
let mut builder = NodeJsChunkingContext::builder(
990991
root_path,
991992
node_root,
993+
node_root_to_root_path,
992994
client_root,
993995
node_root
994996
.join("server/chunks/ssr".into())
@@ -1021,6 +1023,7 @@ pub async fn get_server_chunking_context(
10211023
mode: Vc<NextMode>,
10221024
root_path: ResolvedVc<FileSystemPath>,
10231025
node_root: ResolvedVc<FileSystemPath>,
1026+
node_root_to_root_path: ResolvedVc<RcStr>,
10241027
environment: ResolvedVc<Environment>,
10251028
module_id_strategy: ResolvedVc<Box<dyn ModuleIdStrategy>>,
10261029
turbo_minify: Vc<bool>,
@@ -1032,6 +1035,7 @@ pub async fn get_server_chunking_context(
10321035
let mut builder = NodeJsChunkingContext::builder(
10331036
root_path,
10341037
node_root,
1038+
node_root_to_root_path,
10351039
node_root,
10361040
node_root.join("server/chunks".into()).to_resolved().await?,
10371041
node_root.join("server/assets".into()).to_resolved().await?,
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
const text = import.meta.url
2+
3+
export default function Page() {
4+
return <p>{text}</p>
5+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
'use client'
2+
3+
const text = import.meta.url
4+
5+
export default function Page() {
6+
return <p>{text}</p>
7+
}

test/e2e/app-dir/non-root-project-monorepo/non-root-project-monorepo.test.ts

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,38 @@ describe('non-root-project-monorepo', () => {
4848
})
4949
})
5050

51+
describe('import.meta.url', () => {
52+
it('should work during RSC', async () => {
53+
const $ = await next.render$('/import-meta-url-rsc')
54+
expect($('p').text()).toMatch(
55+
/^file:\/\/.*\/next-install-[^/]+\/apps\/web\/app\/import-meta-url-rsc\/page.tsx$/
56+
)
57+
})
58+
59+
it('should work during SSR', async () => {
60+
const $ = await next.render$('/import-meta-url-ssr')
61+
expect($('p').text()).toMatch(
62+
/^file:\/\/.*\/next-install-[^/]+\/apps\/web\/app\/import-meta-url-ssr\/page.tsx$/
63+
)
64+
})
65+
66+
it('should work on client-side', async () => {
67+
const browser = await next.browser('/import-meta-url-ssr')
68+
await assertNoRedbox(browser)
69+
if (isTurbopack) {
70+
// Turbopack intentionally doesn't expose the full path to the browser bundles
71+
expect(await browser.elementByCss('p').text()).toBe(
72+
'file:///ROOT/apps/web/app/import-meta-url-ssr/page.tsx'
73+
)
74+
} else {
75+
expect(await browser.elementByCss('p').text()).toMatch(
76+
/^file:\/\/.*\/next-install-[^/]+\/apps\/web\/app\/import-meta-url-ssr\/page.tsx$/
77+
)
78+
}
79+
await browser.close()
80+
})
81+
})
82+
5183
if (isNextDev) {
5284
describe('source-maps', () => {
5385
function normalizeStackTrace(stack: string): string {

turbopack/crates/turbopack-browser/src/chunking_context.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,8 @@ pub struct BrowserChunkingContext {
118118
should_use_file_source_map_uris: bool,
119119
/// This path is used to compute the url to request chunks from
120120
output_root: ResolvedVc<FileSystemPath>,
121+
/// The relative path from the output_root to the root_path.
122+
output_root_to_root_path: ResolvedVc<RcStr>,
121123
/// This path is used to compute the url to request assets from
122124
client_root: ResolvedVc<FileSystemPath>,
123125
/// Chunks are placed at this path
@@ -154,6 +156,7 @@ impl BrowserChunkingContext {
154156
pub fn builder(
155157
root_path: ResolvedVc<FileSystemPath>,
156158
output_root: ResolvedVc<FileSystemPath>,
159+
output_root_to_root_path: ResolvedVc<RcStr>,
157160
client_root: ResolvedVc<FileSystemPath>,
158161
chunk_root_path: ResolvedVc<FileSystemPath>,
159162
asset_root_path: ResolvedVc<FileSystemPath>,
@@ -165,6 +168,7 @@ impl BrowserChunkingContext {
165168
name: None,
166169
root_path,
167170
output_root,
171+
output_root_to_root_path,
168172
client_root,
169173
chunk_root_path,
170174
should_use_file_source_map_uris: false,
@@ -286,6 +290,11 @@ impl ChunkingContext for BrowserChunkingContext {
286290
*self.output_root
287291
}
288292

293+
#[turbo_tasks::function]
294+
fn output_root_to_root_path(&self) -> Vc<RcStr> {
295+
*self.output_root_to_root_path
296+
}
297+
289298
#[turbo_tasks::function]
290299
fn environment(&self) -> Vc<Environment> {
291300
*self.environment

turbopack/crates/turbopack-browser/src/ecmascript/evaluate/chunk.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ impl EcmascriptDevEvaluateChunk {
6969
let environment = this.chunking_context.environment();
7070

7171
let output_root = this.chunking_context.output_root().await?;
72+
let output_root_to_root_path = this.chunking_context.output_root_to_root_path();
7273
let chunk_path_vc = self.ident().path();
7374
let chunk_path = chunk_path_vc.await?;
7475
let chunk_public_path = if let Some(path) = output_root.get_path_to(&chunk_path) {
@@ -145,7 +146,7 @@ impl EcmascriptDevEvaluateChunk {
145146
environment,
146147
chunking_context.chunk_base_path(),
147148
Value::new(chunking_context.runtime_type()),
148-
Vc::cell(output_root.to_string().into()),
149+
output_root_to_root_path,
149150
);
150151
code.push_code(&*runtime_code.await?);
151152
}
@@ -154,7 +155,7 @@ impl EcmascriptDevEvaluateChunk {
154155
environment,
155156
chunking_context.chunk_base_path(),
156157
Value::new(chunking_context.runtime_type()),
157-
Vc::cell(output_root.to_string().into()),
158+
output_root_to_root_path,
158159
);
159160
code.push_code(&*runtime_code.await?);
160161
}

turbopack/crates/turbopack-cli/src/build/mod.rs

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -189,19 +189,23 @@ async fn build_internal(
189189
.unwrap_or(project_relative)
190190
.replace(MAIN_SEPARATOR, "/")
191191
.into();
192-
let project_path = project_fs
193-
.root()
194-
.join(project_relative)
195-
.to_resolved()
196-
.await?;
192+
let root_path = project_fs.root().to_resolved().await?;
193+
let project_path = root_path.join(project_relative).to_resolved().await?;
197194
let build_output_root = output_fs.root().join("dist".into()).to_resolved().await?;
198195

199196
let node_env = NodeEnv::Production.cell();
200197

198+
let build_output_root_to_root_path = project_path
199+
.join("dist".into())
200+
.await?
201+
.get_relative_path_to(&*root_path.await?)
202+
.context("Project path is in root path")?;
203+
201204
let chunking_context = Vc::upcast(
202205
NodeJsChunkingContext::builder(
203-
project_path,
206+
root_path,
204207
build_output_root,
208+
ResolvedVc::cell(build_output_root_to_root_path),
205209
build_output_root,
206210
build_output_root,
207211
build_output_root,
@@ -217,7 +221,7 @@ async fn build_internal(
217221

218222
let compile_time_info = get_client_compile_time_info(browserslist_query, node_env);
219223
let execution_context =
220-
ExecutionContext::new(*project_path, chunking_context, load_env(*project_path));
224+
ExecutionContext::new(*root_path, chunking_context, load_env(*root_path));
221225
let asset_context = get_client_asset_context(
222226
*project_path,
223227
execution_context,

0 commit comments

Comments
 (0)