Skip to content

Commit

Permalink
[Turbopack] fix import.meta.url in monorepo (#72612)
Browse files Browse the repository at this point in the history
### 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.
  • Loading branch information
sokra authored Dec 20, 2024
1 parent e79be05 commit 64efdad
Show file tree
Hide file tree
Showing 164 changed files with 262 additions and 135 deletions.
18 changes: 18 additions & 0 deletions crates/next-api/src/project.rs
Original file line number Diff line number Diff line change
Expand Up @@ -647,6 +647,18 @@ impl Project {
))
}

#[turbo_tasks::function]
pub async fn node_root_to_root_path(self: Vc<Self>) -> Result<Vc<RcStr>> {
let this = self.await?;
let output_root_to_root_path = self
.project_path()
.join(this.dist_dir.clone())
.await?
.get_relative_path_to(&*self.project_root_path().await?)
.context("Project path need to be in root path")?;
Ok(Vc::cell(output_root_to_root_path))
}

#[turbo_tasks::function]
pub async fn project_path(self: Vc<Self>) -> Result<Vc<FileSystemPath>> {
let this = self.await?;
Expand Down Expand Up @@ -695,6 +707,7 @@ impl Project {
NodeJsChunkingContext::builder(
self.project_root_path().to_resolved().await?,
node_root,
self.node_root_to_root_path().to_resolved().await?,
node_root,
node_root.join("build/chunks".into()).to_resolved().await?,
node_root.join("build/assets".into()).to_resolved().await?,
Expand Down Expand Up @@ -822,6 +835,7 @@ impl Project {
get_client_chunking_context(
self.project_root_path(),
self.client_relative_path(),
Vc::cell("/ROOT".into()),
self.next_config().computed_asset_prefix(),
self.client_compile_time_info().environment(),
self.next_mode(),
Expand All @@ -840,6 +854,7 @@ impl Project {
self.next_mode(),
self.project_root_path(),
self.node_root(),
self.node_root_to_root_path(),
self.client_relative_path(),
self.next_config().computed_asset_prefix(),
self.server_compile_time_info().environment(),
Expand All @@ -851,6 +866,7 @@ impl Project {
self.next_mode(),
self.project_root_path(),
self.node_root(),
self.node_root_to_root_path(),
self.server_compile_time_info().environment(),
self.module_id_strategy(),
self.next_config().turbo_minify(self.next_mode()),
Expand All @@ -868,6 +884,7 @@ impl Project {
self.next_mode(),
self.project_root_path(),
self.node_root(),
self.node_root_to_root_path(),
self.client_relative_path(),
self.next_config().computed_asset_prefix(),
self.edge_compile_time_info().environment(),
Expand All @@ -879,6 +896,7 @@ impl Project {
self.next_mode(),
self.project_root_path(),
self.node_root(),
self.node_root_to_root_path(),
self.edge_compile_time_info().environment(),
self.module_id_strategy(),
self.next_config().turbo_minify(self.next_mode()),
Expand Down
6 changes: 4 additions & 2 deletions crates/next-core/src/next_client/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -398,8 +398,9 @@ pub async fn get_client_module_options_context(

#[turbo_tasks::function]
pub async fn get_client_chunking_context(
project_path: ResolvedVc<FileSystemPath>,
root_path: ResolvedVc<FileSystemPath>,
client_root: ResolvedVc<FileSystemPath>,
client_root_to_root_path: ResolvedVc<RcStr>,
asset_prefix: ResolvedVc<Option<RcStr>>,
environment: ResolvedVc<Environment>,
mode: Vc<NextMode>,
Expand All @@ -408,8 +409,9 @@ pub async fn get_client_chunking_context(
) -> Result<Vc<Box<dyn ChunkingContext>>> {
let next_mode = mode.await?;
let mut builder = BrowserChunkingContext::builder(
project_path,
root_path,
client_root,
client_root_to_root_path,
client_root,
client_root
.join("static/chunks".into())
Expand Down
12 changes: 8 additions & 4 deletions crates/next-core/src/next_edge/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -200,8 +200,9 @@ pub async fn get_edge_resolve_options_context(
#[turbo_tasks::function]
pub async fn get_edge_chunking_context_with_client_assets(
mode: Vc<NextMode>,
project_path: ResolvedVc<FileSystemPath>,
root_path: ResolvedVc<FileSystemPath>,
node_root: ResolvedVc<FileSystemPath>,
output_root_to_root_path: ResolvedVc<RcStr>,
client_root: ResolvedVc<FileSystemPath>,
asset_prefix: ResolvedVc<Option<RcStr>>,
environment: ResolvedVc<Environment>,
Expand All @@ -212,8 +213,9 @@ pub async fn get_edge_chunking_context_with_client_assets(
let next_mode = mode.await?;
Ok(Vc::upcast(
BrowserChunkingContext::builder(
project_path,
root_path,
output_root,
output_root_to_root_path,
client_root,
output_root.join("chunks/ssr".into()).to_resolved().await?,
client_root
Expand All @@ -237,8 +239,9 @@ pub async fn get_edge_chunking_context_with_client_assets(
#[turbo_tasks::function]
pub async fn get_edge_chunking_context(
mode: Vc<NextMode>,
project_path: ResolvedVc<FileSystemPath>,
root_path: ResolvedVc<FileSystemPath>,
node_root: ResolvedVc<FileSystemPath>,
node_root_to_root_path: ResolvedVc<RcStr>,
environment: ResolvedVc<Environment>,
module_id_strategy: ResolvedVc<Box<dyn ModuleIdStrategy>>,
turbo_minify: Vc<bool>,
Expand All @@ -247,8 +250,9 @@ pub async fn get_edge_chunking_context(
let next_mode = mode.await?;
Ok(Vc::upcast(
BrowserChunkingContext::builder(
project_path,
root_path,
output_root,
node_root_to_root_path,
output_root,
output_root.join("chunks".into()).to_resolved().await?,
output_root.join("assets".into()).to_resolved().await?,
Expand Down
4 changes: 4 additions & 0 deletions crates/next-core/src/next_server/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -976,6 +976,7 @@ pub async fn get_server_chunking_context_with_client_assets(
mode: Vc<NextMode>,
root_path: ResolvedVc<FileSystemPath>,
node_root: ResolvedVc<FileSystemPath>,
node_root_to_root_path: ResolvedVc<RcStr>,
client_root: ResolvedVc<FileSystemPath>,
asset_prefix: ResolvedVc<Option<RcStr>>,
environment: ResolvedVc<Environment>,
Expand All @@ -989,6 +990,7 @@ pub async fn get_server_chunking_context_with_client_assets(
let mut builder = NodeJsChunkingContext::builder(
root_path,
node_root,
node_root_to_root_path,
client_root,
node_root
.join("server/chunks/ssr".into())
Expand Down Expand Up @@ -1021,6 +1023,7 @@ pub async fn get_server_chunking_context(
mode: Vc<NextMode>,
root_path: ResolvedVc<FileSystemPath>,
node_root: ResolvedVc<FileSystemPath>,
node_root_to_root_path: ResolvedVc<RcStr>,
environment: ResolvedVc<Environment>,
module_id_strategy: ResolvedVc<Box<dyn ModuleIdStrategy>>,
turbo_minify: Vc<bool>,
Expand All @@ -1032,6 +1035,7 @@ pub async fn get_server_chunking_context(
let mut builder = NodeJsChunkingContext::builder(
root_path,
node_root,
node_root_to_root_path,
node_root,
node_root.join("server/chunks".into()).to_resolved().await?,
node_root.join("server/assets".into()).to_resolved().await?,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
const text = import.meta.url

export default function Page() {
return <p>{text}</p>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
'use client'

const text = import.meta.url

export default function Page() {
return <p>{text}</p>
}
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,38 @@ describe('non-root-project-monorepo', () => {
})
})

describe('import.meta.url', () => {
it('should work during RSC', async () => {
const $ = await next.render$('/import-meta-url-rsc')
expect($('p').text()).toMatch(
/^file:\/\/.*\/next-install-[^/]+\/apps\/web\/app\/import-meta-url-rsc\/page.tsx$/
)
})

it('should work during SSR', async () => {
const $ = await next.render$('/import-meta-url-ssr')
expect($('p').text()).toMatch(
/^file:\/\/.*\/next-install-[^/]+\/apps\/web\/app\/import-meta-url-ssr\/page.tsx$/
)
})

it('should work on client-side', async () => {
const browser = await next.browser('/import-meta-url-ssr')
await assertNoRedbox(browser)
if (isTurbopack) {
// Turbopack intentionally doesn't expose the full path to the browser bundles
expect(await browser.elementByCss('p').text()).toBe(
'file:///ROOT/apps/web/app/import-meta-url-ssr/page.tsx'
)
} else {
expect(await browser.elementByCss('p').text()).toMatch(
/^file:\/\/.*\/next-install-[^/]+\/apps\/web\/app\/import-meta-url-ssr\/page.tsx$/
)
}
await browser.close()
})
})

if (isNextDev) {
describe('source-maps', () => {
function normalizeStackTrace(stack: string): string {
Expand Down
9 changes: 9 additions & 0 deletions turbopack/crates/turbopack-browser/src/chunking_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,8 @@ pub struct BrowserChunkingContext {
should_use_file_source_map_uris: bool,
/// This path is used to compute the url to request chunks from
output_root: ResolvedVc<FileSystemPath>,
/// The relative path from the output_root to the root_path.
output_root_to_root_path: ResolvedVc<RcStr>,
/// This path is used to compute the url to request assets from
client_root: ResolvedVc<FileSystemPath>,
/// Chunks are placed at this path
Expand Down Expand Up @@ -154,6 +156,7 @@ impl BrowserChunkingContext {
pub fn builder(
root_path: ResolvedVc<FileSystemPath>,
output_root: ResolvedVc<FileSystemPath>,
output_root_to_root_path: ResolvedVc<RcStr>,
client_root: ResolvedVc<FileSystemPath>,
chunk_root_path: ResolvedVc<FileSystemPath>,
asset_root_path: ResolvedVc<FileSystemPath>,
Expand All @@ -165,6 +168,7 @@ impl BrowserChunkingContext {
name: None,
root_path,
output_root,
output_root_to_root_path,
client_root,
chunk_root_path,
should_use_file_source_map_uris: false,
Expand Down Expand Up @@ -286,6 +290,11 @@ impl ChunkingContext for BrowserChunkingContext {
*self.output_root
}

#[turbo_tasks::function]
fn output_root_to_root_path(&self) -> Vc<RcStr> {
*self.output_root_to_root_path
}

#[turbo_tasks::function]
fn environment(&self) -> Vc<Environment> {
*self.environment
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ impl EcmascriptDevEvaluateChunk {
let environment = this.chunking_context.environment();

let output_root = this.chunking_context.output_root().await?;
let output_root_to_root_path = this.chunking_context.output_root_to_root_path();
let chunk_path_vc = self.ident().path();
let chunk_path = chunk_path_vc.await?;
let chunk_public_path = if let Some(path) = output_root.get_path_to(&chunk_path) {
Expand Down Expand Up @@ -145,7 +146,7 @@ impl EcmascriptDevEvaluateChunk {
environment,
chunking_context.chunk_base_path(),
Value::new(chunking_context.runtime_type()),
Vc::cell(output_root.to_string().into()),
output_root_to_root_path,
);
code.push_code(&*runtime_code.await?);
}
Expand All @@ -154,7 +155,7 @@ impl EcmascriptDevEvaluateChunk {
environment,
chunking_context.chunk_base_path(),
Value::new(chunking_context.runtime_type()),
Vc::cell(output_root.to_string().into()),
output_root_to_root_path,
);
code.push_code(&*runtime_code.await?);
}
Expand Down
18 changes: 11 additions & 7 deletions turbopack/crates/turbopack-cli/src/build/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -189,19 +189,23 @@ async fn build_internal(
.unwrap_or(project_relative)
.replace(MAIN_SEPARATOR, "/")
.into();
let project_path = project_fs
.root()
.join(project_relative)
.to_resolved()
.await?;
let root_path = project_fs.root().to_resolved().await?;
let project_path = root_path.join(project_relative).to_resolved().await?;
let build_output_root = output_fs.root().join("dist".into()).to_resolved().await?;

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

let build_output_root_to_root_path = project_path
.join("dist".into())
.await?
.get_relative_path_to(&*root_path.await?)
.context("Project path is in root path")?;

let chunking_context = Vc::upcast(
NodeJsChunkingContext::builder(
project_path,
root_path,
build_output_root,
ResolvedVc::cell(build_output_root_to_root_path),
build_output_root,
build_output_root,
build_output_root,
Expand All @@ -217,7 +221,7 @@ async fn build_internal(

let compile_time_info = get_client_compile_time_info(browserslist_query, node_env);
let execution_context =
ExecutionContext::new(*project_path, chunking_context, load_env(*project_path));
ExecutionContext::new(*root_path, chunking_context, load_env(*root_path));
let asset_context = get_client_asset_context(
*project_path,
execution_context,
Expand Down
24 changes: 17 additions & 7 deletions turbopack/crates/turbopack-cli/src/dev/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -242,19 +242,28 @@ async fn source(
.into();

let output_fs = output_fs(project_dir);
let fs = project_fs(root_dir);
let project_path = fs.root().join(project_relative).to_resolved().await?;
let fs: Vc<Box<dyn FileSystem>> = project_fs(root_dir);
let root_path = fs.root().to_resolved().await?;
let project_path = root_path.join(project_relative).to_resolved().await?;

let env = load_env(*project_path);
let env = load_env(*root_path);
let build_output_root = output_fs
.root()
.join(".turbopack/build".into())
.to_resolved()
.await?;

let build_output_root_to_root_path = project_path
.join(".turbopack/build".into())
.await?
.get_relative_path_to(&*root_path.await?)
.context("Project path is in root path")?;
let build_output_root_to_root_path = ResolvedVc::cell(build_output_root_to_root_path);

let build_chunking_context = NodeJsChunkingContext::builder(
project_path,
root_path,
build_output_root,
build_output_root_to_root_path,
build_output_root,
build_output_root
.join("chunks".into())
Expand All @@ -270,7 +279,7 @@ async fn source(
.build();

let execution_context =
ExecutionContext::new(*project_path, Vc::upcast(build_chunking_context), env);
ExecutionContext::new(*root_path, Vc::upcast(build_chunking_context), env);

let server_fs = Vc::upcast::<Box<dyn FileSystem>>(ServerFileSystem::new());
let server_root = server_fs.root();
Expand All @@ -292,11 +301,12 @@ async fn source(
})
.collect();

let web_source = create_web_entry_source(
*project_path,
let web_source: ResolvedVc<Box<dyn ContentSource>> = create_web_entry_source(
*root_path,
execution_context,
entry_requests,
server_root,
Vc::cell("/ROOT".into()),
env,
eager_compile,
NodeEnv::Development.cell(),
Expand Down
Loading

0 comments on commit 64efdad

Please sign in to comment.