Skip to content

Commit

Permalink
Configure the path of the Node.js entry chunk (#5398)
Browse files Browse the repository at this point in the history
### Description

This PR allows configuring a specific path to Node.js entry chunks.
Before, these
would be generated under most of the same rules as dev chunks. However,
in some
cases, Next.js expects these chunks to be under a specific path. In any
case,
having unique chunk paths isn't particularly useful on the server-side.

### Testing Instructions

N/A
  • Loading branch information
alexkirsz authored Jul 6, 2023
1 parent ed9a5c6 commit 006b5b1
Show file tree
Hide file tree
Showing 8 changed files with 105 additions and 128 deletions.
76 changes: 29 additions & 47 deletions crates/turbopack-build/src/chunking_context.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use anyhow::Result;
use anyhow::{bail, Result};
use indexmap::IndexSet;
use turbo_tasks::{
graph::{AdjacencyMap, GraphTraversal},
Expand All @@ -16,14 +16,14 @@ use turbopack_core::{
ident::AssetIdentVc,
};
use turbopack_css::chunk::CssChunkVc;
use turbopack_ecmascript::{
chunk::{EcmascriptChunkVc, EcmascriptChunkingContext, EcmascriptChunkingContextVc},
EcmascriptModuleAssetVc,
use turbopack_ecmascript::chunk::{
EcmascriptChunkPlaceableVc, EcmascriptChunkVc, EcmascriptChunkingContext,
EcmascriptChunkingContextVc,
};
use turbopack_ecmascript_runtime::RuntimeType;

use crate::ecmascript::node::{
chunk::EcmascriptBuildNodeChunkVc, evaluate::chunk::EcmascriptBuildNodeEvaluateChunkVc,
chunk::EcmascriptBuildNodeChunkVc, entry::chunk::EcmascriptBuildNodeEntryChunkVc,
};

/// A builder for [`BuildChunkingContextVc`].
Expand All @@ -37,6 +37,11 @@ impl BuildChunkingContextBuilder {
self
}

pub fn layer(mut self, layer: impl Into<String>) -> Self {
self.context.layer = Some(layer.into());
self
}

/// Builds the chunking context.
pub fn build(self) -> BuildChunkingContextVc {
BuildChunkingContextVc::new(Value::new(self.context))
Expand Down Expand Up @@ -104,46 +109,32 @@ impl BuildChunkingContextVc {
this.into_value().cell()
}

#[turbo_tasks::function]
fn generate_evaluate_chunk(
self_vc: BuildChunkingContextVc,
entry_chunk: ChunkVc,
other_chunks: AssetsVc,
evaluatable_assets: EvaluatableAssetsVc,
exported_module: Option<EcmascriptModuleAssetVc>,
) -> AssetVc {
EcmascriptBuildNodeEvaluateChunkVc::new(
self_vc,
entry_chunk,
other_chunks,
evaluatable_assets,
exported_module,
)
.into()
}

/// Generates an output chunk that:
/// * evaluates the given assets; and
/// * exports the result of evaluating the given module as a CommonJS
/// default export.
#[turbo_tasks::function]
pub async fn generate_exported_chunk(
pub async fn generate_entry_chunk(
self_vc: BuildChunkingContextVc,
module: EcmascriptModuleAssetVc,
path: FileSystemPathVc,
module: EcmascriptChunkPlaceableVc,
evaluatable_assets: EvaluatableAssetsVc,
) -> Result<AssetVc> {
let entry_chunk = module.as_root_chunk(self_vc.into());

let assets = self_vc
.get_evaluate_chunk_assets(entry_chunk, evaluatable_assets)
let other_chunks = self_vc
.get_chunk_assets(entry_chunk, evaluatable_assets)
.await?;

let asset = self_vc.generate_evaluate_chunk(
let asset = EcmascriptBuildNodeEntryChunkVc::new(
path,
self_vc,
entry_chunk,
AssetsVc::cell(assets),
AssetsVc::cell(other_chunks),
evaluatable_assets,
Some(module),
);
module,
)
.into();

Ok(asset)
}
Expand All @@ -161,7 +152,7 @@ impl BuildChunkingContextVc {
}

impl BuildChunkingContextVc {
async fn get_evaluate_chunk_assets(
async fn get_chunk_assets(
self,
entry_chunk: ChunkVc,
evaluatable_assets: EvaluatableAssetsVc,
Expand Down Expand Up @@ -296,22 +287,13 @@ impl ChunkingContext for BuildChunkingContext {

#[turbo_tasks::function]
async fn evaluated_chunk_group(
self_vc: BuildChunkingContextVc,
entry_chunk: ChunkVc,
evaluatable_assets: EvaluatableAssetsVc,
_self_vc: BuildChunkingContextVc,
_entry_chunk: ChunkVc,
_evaluatable_assets: EvaluatableAssetsVc,
) -> Result<AssetsVc> {
let mut assets = self_vc
.get_evaluate_chunk_assets(entry_chunk, evaluatable_assets)
.await?;

assets.push(self_vc.generate_evaluate_chunk(
entry_chunk,
AssetsVc::cell(assets.clone()),
evaluatable_assets,
None,
));

Ok(AssetsVc::cell(assets))
// TODO(alexkirsz) This method should be part of a separate trait that is
// only implemented for client/edge runtimes.
bail!("the build chunking context does not support evaluated chunk groups")
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ use std::io::Write;

use anyhow::{bail, Result};
use indoc::writedoc;
use turbo_tasks::{primitives::StringVc, Value, ValueToString, ValueToStringVc};
use turbo_tasks_fs::File;
use turbo_tasks::{primitives::StringVc, ValueToString, ValueToStringVc};
use turbo_tasks_fs::{File, FileSystemPathVc};
use turbopack_core::{
asset::{Asset, AssetContentVc, AssetVc, AssetsVc},
chunk::{ChunkVc, ChunkingContext, EvaluatableAssetsVc},
Expand All @@ -17,7 +17,6 @@ use turbopack_core::{
use turbopack_ecmascript::{
chunk::{EcmascriptChunkPlaceable, EcmascriptChunkPlaceableVc},
utils::StringifyJs,
EcmascriptModuleAssetVc,
};

use super::runtime::EcmascriptBuildNodeRuntimeReferenceVc;
Expand All @@ -26,26 +25,29 @@ use crate::BuildChunkingContextVc;
/// An Ecmascript chunk that loads a list of parallel chunks, then instantiates
/// runtime entries.
#[turbo_tasks::value(shared)]
pub(crate) struct EcmascriptBuildNodeEvaluateChunk {
pub(crate) struct EcmascriptBuildNodeEntryChunk {
path: FileSystemPathVc,
chunking_context: BuildChunkingContextVc,
entry_chunk: ChunkVc,
other_chunks: AssetsVc,
evaluatable_assets: EvaluatableAssetsVc,
exported_module: Option<EcmascriptModuleAssetVc>,
exported_module: EcmascriptChunkPlaceableVc,
}

#[turbo_tasks::value_impl]
impl EcmascriptBuildNodeEvaluateChunkVc {
/// Creates a new [`EcmascriptBuildNodeEvaluateChunkVc`].
impl EcmascriptBuildNodeEntryChunkVc {
/// Creates a new [`EcmascriptBuildNodeEntryChunkVc`].
#[turbo_tasks::function]
pub fn new(
path: FileSystemPathVc,
chunking_context: BuildChunkingContextVc,
entry_chunk: ChunkVc,
other_chunks: AssetsVc,
evaluatable_assets: EvaluatableAssetsVc,
exported_module: Option<EcmascriptModuleAssetVc>,
exported_module: EcmascriptChunkPlaceableVc,
) -> Self {
EcmascriptBuildNodeEvaluateChunk {
EcmascriptBuildNodeEntryChunk {
path,
chunking_context,
entry_chunk,
other_chunks,
Expand Down Expand Up @@ -136,20 +138,19 @@ impl EcmascriptBuildNodeEvaluateChunkVc {
}
}

if let Some(exported_module) = this.exported_module {
let runtime_module_id = exported_module
.as_chunk_item(this.chunking_context.into())
.id()
.await?;
let runtime_module_id = this
.exported_module
.as_chunk_item(this.chunking_context.into())
.id()
.await?;

writedoc!(
code,
r#"
writedoc!(
code,
r#"
module.exports = runtime.getOrInstantiateRuntimeModule({}, CHUNK_PUBLIC_PATH).exports;
"#,
StringifyJs(&*runtime_module_id),
)?;
}
StringifyJs(&*runtime_module_id),
)?;

Ok(CodeVc::cell(code.build()))
}
Expand All @@ -164,7 +165,7 @@ impl EcmascriptBuildNodeEvaluateChunkVc {
}

#[turbo_tasks::value_impl]
impl ValueToString for EcmascriptBuildNodeEvaluateChunk {
impl ValueToString for EcmascriptBuildNodeEntryChunk {
#[turbo_tasks::function]
async fn to_string(&self) -> Result<StringVc> {
Ok(StringVc::cell(
Expand All @@ -184,32 +185,14 @@ fn chunk_reference_description() -> StringVc {
}

#[turbo_tasks::value_impl]
impl Asset for EcmascriptBuildNodeEvaluateChunk {
impl Asset for EcmascriptBuildNodeEntryChunk {
#[turbo_tasks::function]
async fn ident(&self) -> Result<AssetIdentVc> {
let mut ident = self.entry_chunk.ident().await?.clone_value();

ident.add_modifier(modifier());

ident.modifiers.extend(
self.evaluatable_assets
.await?
.iter()
.map(|entry| entry.ident().to_string()),
);

for chunk in &*self.other_chunks.await? {
ident.add_modifier(chunk.ident().to_string());
}

let ident = AssetIdentVc::new(Value::new(ident));
Ok(AssetIdentVc::from_path(
self.chunking_context.chunk_path(ident, ".js"),
))
fn ident(&self) -> AssetIdentVc {
AssetIdentVc::from_path(self.path)
}

#[turbo_tasks::function]
async fn references(self_vc: EcmascriptBuildNodeEvaluateChunkVc) -> Result<AssetReferencesVc> {
async fn references(self_vc: EcmascriptBuildNodeEntryChunkVc) -> Result<AssetReferencesVc> {
let this = self_vc.await?;
let mut references = vec![self_vc.runtime_reference().into()];

Expand All @@ -232,16 +215,16 @@ impl Asset for EcmascriptBuildNodeEvaluateChunk {
}

#[turbo_tasks::function]
async fn content(self_vc: EcmascriptBuildNodeEvaluateChunkVc) -> Result<AssetContentVc> {
async fn content(self_vc: EcmascriptBuildNodeEntryChunkVc) -> Result<AssetContentVc> {
let code = self_vc.code().await?;
Ok(File::from(code.source_code().clone()).into())
}
}

#[turbo_tasks::value_impl]
impl GenerateSourceMap for EcmascriptBuildNodeEvaluateChunk {
impl GenerateSourceMap for EcmascriptBuildNodeEntryChunk {
#[turbo_tasks::function]
fn generate_source_map(self_vc: EcmascriptBuildNodeEvaluateChunkVc) -> OptionSourceMapVc {
fn generate_source_map(self_vc: EcmascriptBuildNodeEntryChunkVc) -> OptionSourceMapVc {
self_vc.code().generate_source_map()
}
}
2 changes: 1 addition & 1 deletion crates/turbopack-build/src/ecmascript/node/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
pub(crate) mod chunk;
pub(crate) mod content;
pub(crate) mod evaluate;
pub(crate) mod entry;
Loading

0 comments on commit 006b5b1

Please sign in to comment.