Skip to content

Commit

Permalink
refactor asset identification (vercel/turborepo#3999)
Browse files Browse the repository at this point in the history
* add Asset::ident() as unique identifier of an Asset
* add ChunkItem::ident() instead of ChunkItem::to_string()
(ValueToString)
* base `chunk_path` on AssetIdent instead of path only

Motivation:

We want to get rid of the `import "."` in favor of inner assets. When
doing this we no longer need to place virtual assets below the actual
file path and they can stay in their original path. But placing virtual
assets below the actual asset also made the `Asset::path` unique, which
would no longer be the case after using inner assets. Some parts of the
code base relied on `Asset::path` being unique (e. g. module ids and
chunk paths). But actually we never guaranteed that to be unique.
After this PR `Asset::ident` is intended to be unique and allow to carry
more information than only the path:
* Query string (`module?query`)
* Fragment (`module#fragment`)
* Asset (additional wrapped assets by key value pairs)
* Modifiers (additional transformations applied on the module, e. g.
`chunks`, `client chunks`)
* In future: Part (select a subpart of the module, e. g. only export
abc, or the module evaluation, or some internal part)
  • Loading branch information
sokra authored Mar 1, 2023
1 parent b62b6d0 commit be1352f
Show file tree
Hide file tree
Showing 171 changed files with 1,047 additions and 909 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ impl Transition for NextLayoutEntryTransition {
#[turbo_tasks::function]
fn process_source(&self, asset: AssetVc) -> AssetVc {
VirtualAssetVc::new(
asset.path().join("layout-entry.tsx"),
asset.ident().path().join("layout-entry.tsx"),
next_js_file("entry/app/layout-entry.tsx").into(),
)
.into()
Expand Down
3 changes: 2 additions & 1 deletion crates/next-core/src/app_source.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use std::{
};

use anyhow::{anyhow, Result};
use indexmap::IndexMap;
use turbo_tasks::{TryJoinIterExt, Value, ValueToString};
use turbo_tasks_env::ProcessEnvVc;
use turbo_tasks_fs::{rebase, rope::RopeBuilder, File, FileContent, FileSystemPathVc};
Expand Down Expand Up @@ -716,7 +717,7 @@ impl AppRouteVc {
Value::new(EcmascriptModuleAssetType::Typescript),
EcmascriptInputTransformsVc::cell(vec![EcmascriptInputTransform::TypeScript]),
this.context.compile_time_info(),
InnerAssetsVc::cell(HashMap::from([("ROUTE_CHUNK_GROUP".to_string(), entry)])),
InnerAssetsVc::cell(IndexMap::from([("ROUTE_CHUNK_GROUP".to_string(), entry)])),
),
chunking_context,
intermediate_output_path: this.intermediate_output_path,
Expand Down
2 changes: 1 addition & 1 deletion crates/next-core/src/next_client/runtime_entry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ impl RuntimeEntryVc {
bail!(
"runtime reference resolved to an asset ({}) that is not placeable into an \
ecmascript chunk",
asset.path().to_string().await?
asset.ident().to_string().await?
);
}
}
Expand Down
9 changes: 6 additions & 3 deletions crates/next-core/src/next_client/transition.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,13 @@ impl Transition for NextClientTransition {
fn process_source(&self, asset: AssetVc) -> AssetVc {
if self.is_app {
VirtualAssetVc::new(
asset.path().join("next-app-hydrate.tsx"),
asset.ident().path().join("next-app-hydrate.tsx"),
next_js_file("entry/app/hydrate.tsx").into(),
)
.into()
} else {
VirtualAssetVc::new(
asset.path().join("next-hydrate.tsx"),
asset.ident().path().join("next-hydrate.tsx"),
next_js_file("entry/next-hydrate.tsx").into(),
)
.into()
Expand Down Expand Up @@ -85,7 +85,10 @@ impl Transition for NextClientTransition {
) -> Result<AssetVc> {
let chunkable_asset = match ChunkableAssetVc::resolve_from(asset).await? {
Some(chunkable_asset) => chunkable_asset,
None => bail!("asset {} is not chunkable", asset.path().to_string().await?),
None => bail!(
"asset {} is not chunkable",
asset.ident().to_string().await?
),
};

let runtime_entries = self.runtime_entries.resolve_entries(context.into());
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,21 @@
use anyhow::Result;
use turbo_tasks_fs::FileSystemPathVc;
use turbo_tasks::primitives::StringVc;
use turbopack::ecmascript::chunk::{
EcmascriptChunkItemVc, EcmascriptChunkPlaceable, EcmascriptChunkPlaceableVc, EcmascriptChunkVc,
EcmascriptExportsVc,
};
use turbopack_core::{
asset::{Asset, AssetContentVc, AssetVc},
chunk::{ChunkVc, ChunkableAsset, ChunkableAssetVc, ChunkingContextVc},
ident::AssetIdentVc,
reference::AssetReferencesVc,
};

#[turbo_tasks::function]
fn modifier() -> StringVc {
StringVc::cell("in chunking context".to_string())
}

#[turbo_tasks::value(shared)]
pub struct InChunkingContextAsset {
pub asset: EcmascriptChunkPlaceableVc,
Expand All @@ -19,8 +25,8 @@ pub struct InChunkingContextAsset {
#[turbo_tasks::value_impl]
impl Asset for InChunkingContextAsset {
#[turbo_tasks::function]
fn path(&self) -> FileSystemPathVc {
self.asset.path()
fn ident(&self) -> AssetIdentVc {
self.asset.ident().with_modifier(modifier())
}

#[turbo_tasks::function]
Expand Down
39 changes: 17 additions & 22 deletions crates/next-core/src/next_client_chunks/with_chunks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,22 @@ use turbopack::ecmascript::{
use turbopack_core::{
asset::{Asset, AssetContentVc, AssetVc},
chunk::{
ChunkGroupVc, ChunkItem, ChunkItemVc, ChunkVc, ChunkableAsset, ChunkableAssetReference,
ChunkableAssetReferenceVc, ChunkableAssetVc, ChunkingContextVc, ChunkingType,
ChunkingTypeOptionVc,
Chunk, ChunkGroupVc, ChunkItem, ChunkItemVc, ChunkVc, ChunkableAsset,
ChunkableAssetReference, ChunkableAssetReferenceVc, ChunkableAssetVc, ChunkingContextVc,
ChunkingType, ChunkingTypeOptionVc,
},
ident::AssetIdentVc,
reference::{AssetReference, AssetReferenceVc, AssetReferencesVc},
resolve::{ResolveResult, ResolveResultVc},
};

use super::in_chunking_context_asset::InChunkingContextAsset;

#[turbo_tasks::function]
fn modifier() -> StringVc {
StringVc::cell("chunks".to_string())
}

#[turbo_tasks::value(shared)]
pub struct WithChunksAsset {
pub asset: EcmascriptChunkPlaceableVc,
Expand All @@ -33,8 +39,8 @@ pub struct WithChunksAsset {
#[turbo_tasks::value_impl]
impl Asset for WithChunksAsset {
#[turbo_tasks::function]
fn path(&self) -> FileSystemPathVc {
self.asset.path().join("with-chunks.js")
fn ident(&self) -> AssetIdentVc {
self.asset.ident().with_modifier(modifier())
}

#[turbo_tasks::function]
Expand Down Expand Up @@ -87,29 +93,13 @@ struct WithChunksChunkItem {
inner: WithChunksAssetVc,
}

#[turbo_tasks::value_impl]
impl ValueToString for WithChunksChunkItem {
#[turbo_tasks::function]
async fn to_string(&self) -> Result<StringVc> {
Ok(StringVc::cell(format!(
"{}/with-chunks.js",
self.inner.await?.asset.path().to_string().await?
)))
}
}

#[turbo_tasks::value_impl]
impl EcmascriptChunkItem for WithChunksChunkItem {
#[turbo_tasks::function]
fn chunking_context(&self) -> ChunkingContextVc {
self.context
}

#[turbo_tasks::function]
fn related_path(&self) -> FileSystemPathVc {
self.inner.path()
}

#[turbo_tasks::function]
async fn content(&self) -> Result<EcmascriptChunkItemContentVc> {
let inner = self.inner.await?;
Expand Down Expand Up @@ -143,6 +133,11 @@ const chunks = {};

#[turbo_tasks::value_impl]
impl ChunkItem for WithChunksChunkItem {
#[turbo_tasks::function]
fn asset_ident(&self) -> AssetIdentVc {
self.inner.ident()
}

#[turbo_tasks::function]
async fn references(&self) -> Result<AssetReferencesVc> {
let inner = self.inner.await?;
Expand Down Expand Up @@ -170,7 +165,7 @@ impl ValueToString for WithChunksAssetReference {
async fn to_string(&self) -> Result<StringVc> {
Ok(StringVc::cell(format!(
"referenced asset {}",
self.asset.path().to_string().await?
self.asset.ident().to_string().await?
)))
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ impl Transition for NextServerToClientTransition {
#[turbo_tasks::function]
fn process_source(&self, asset: AssetVc) -> AssetVc {
VirtualAssetVc::new(
asset.path().join("client-proxy.tsx"),
asset.ident().path().join("client-proxy.tsx"),
next_js_file(if self.ssr {
"entry/app/server-to-client-ssr.tsx"
} else {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,21 @@
use anyhow::Result;
use turbo_tasks_fs::FileSystemPathVc;
use turbo_tasks::primitives::StringVc;
use turbopack::ecmascript::chunk::{
EcmascriptChunkItemVc, EcmascriptChunkPlaceable, EcmascriptChunkPlaceableVc, EcmascriptChunkVc,
EcmascriptExportsVc,
};
use turbopack_core::{
asset::{Asset, AssetContentVc, AssetVc},
chunk::{ChunkVc, ChunkableAsset, ChunkableAssetVc, ChunkingContext, ChunkingContextVc},
ident::AssetIdentVc,
reference::AssetReferencesVc,
};

#[turbo_tasks::function]
fn modifier() -> StringVc {
StringVc::cell("with chunking context scope".to_string())
}

#[turbo_tasks::value(shared)]
pub struct WithChunkingContextScopeAsset {
pub asset: EcmascriptChunkPlaceableVc,
Expand All @@ -19,8 +25,8 @@ pub struct WithChunkingContextScopeAsset {
#[turbo_tasks::value_impl]
impl Asset for WithChunkingContextScopeAsset {
#[turbo_tasks::function]
fn path(&self) -> FileSystemPathVc {
self.asset.path()
fn ident(&self) -> AssetIdentVc {
self.asset.ident().with_modifier(modifier())
}

#[turbo_tasks::function]
Expand Down
41 changes: 18 additions & 23 deletions crates/next-core/src/next_client_component/with_client_chunks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,22 @@ use turbopack::ecmascript::{
use turbopack_core::{
asset::{Asset, AssetContentVc, AssetVc},
chunk::{
ChunkGroupVc, ChunkItem, ChunkItemVc, ChunkVc, ChunkableAsset, ChunkableAssetReference,
ChunkableAssetReferenceVc, ChunkableAssetVc, ChunkingContext, ChunkingContextVc,
ChunkingType, ChunkingTypeOptionVc,
Chunk, ChunkGroupVc, ChunkItem, ChunkItemVc, ChunkVc, ChunkableAsset,
ChunkableAssetReference, ChunkableAssetReferenceVc, ChunkableAssetVc, ChunkingContext,
ChunkingContextVc, ChunkingType, ChunkingTypeOptionVc,
},
ident::AssetIdentVc,
reference::{AssetReference, AssetReferenceVc, AssetReferencesVc},
resolve::{ResolveResult, ResolveResultVc},
};

use crate::next_client_chunks::in_chunking_context_asset::InChunkingContextAsset;

#[turbo_tasks::function]
fn modifier() -> StringVc {
StringVc::cell("client chunks".to_string())
}

#[turbo_tasks::value(shared)]
pub struct WithClientChunksAsset {
pub asset: EcmascriptChunkPlaceableVc,
Expand All @@ -32,8 +38,8 @@ pub struct WithClientChunksAsset {
#[turbo_tasks::value_impl]
impl Asset for WithClientChunksAsset {
#[turbo_tasks::function]
fn path(&self) -> FileSystemPathVc {
self.asset.path().join("with-client-chunks.js")
fn ident(&self) -> AssetIdentVc {
self.asset.ident().with_modifier(modifier())
}

#[turbo_tasks::function]
Expand Down Expand Up @@ -87,29 +93,13 @@ struct WithClientChunksChunkItem {
inner: WithClientChunksAssetVc,
}

#[turbo_tasks::value_impl]
impl ValueToString for WithClientChunksChunkItem {
#[turbo_tasks::function]
async fn to_string(&self) -> Result<StringVc> {
Ok(StringVc::cell(format!(
"{}/with-client-chunks.js",
self.inner.await?.asset.path().to_string().await?
)))
}
}

#[turbo_tasks::value_impl]
impl EcmascriptChunkItem for WithClientChunksChunkItem {
#[turbo_tasks::function]
fn chunking_context(&self) -> ChunkingContextVc {
self.context
}

#[turbo_tasks::function]
fn related_path(&self) -> FileSystemPathVc {
self.inner.path()
}

#[turbo_tasks::function]
async fn content(&self) -> Result<EcmascriptChunkItemContentVc> {
let inner = self.inner.await?;
Expand All @@ -122,7 +112,7 @@ impl EcmascriptChunkItem for WithClientChunksChunkItem {
for reference in chunk.references().await?.iter() {
let assets = &*reference.resolve_reference().primary_assets().await?;
for asset in assets.iter() {
asset_paths.push(asset.path().await?);
asset_paths.push(asset.ident().path().await?);
}
}

Expand Down Expand Up @@ -158,6 +148,11 @@ impl EcmascriptChunkItem for WithClientChunksChunkItem {

#[turbo_tasks::value_impl]
impl ChunkItem for WithClientChunksChunkItem {
#[turbo_tasks::function]
fn asset_ident(&self) -> AssetIdentVc {
self.inner.ident()
}

#[turbo_tasks::function]
async fn references(&self) -> Result<AssetReferencesVc> {
let inner = self.inner.await?;
Expand Down Expand Up @@ -187,7 +182,7 @@ impl ValueToString for WithClientChunksAssetReference {
async fn to_string(&self) -> Result<StringVc> {
Ok(StringVc::cell(format!(
"local asset {}",
self.asset.path().to_string().await?
self.asset.ident().to_string().await?
)))
}
}
Expand Down
5 changes: 3 additions & 2 deletions crates/next-core/src/next_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ use turbopack::evaluate_context::node_evaluate_asset_context;
use turbopack_core::{
asset::Asset,
context::AssetContext,
ident::AssetIdentVc,
reference_type::{EntryReferenceSubType, ReferenceType},
resolve::{
find_context_file,
Expand Down Expand Up @@ -570,7 +571,7 @@ pub async fn load_next_config(execution_context: ExecutionContextVc) -> Result<N
EcmascriptChunkPlaceablesVc::cell(vec![config_chunk])
});
let asset_path = config_asset
.map_or(project_root, |a| a.path())
.map_or(project_root, |a| a.ident().path())
.join("load-next-config.js");
let load_next_config_asset = context.process(
next_asset(asset_path, "entry/config/next.js"),
Expand All @@ -581,7 +582,7 @@ pub async fn load_next_config(execution_context: ExecutionContextVc) -> Result<N
load_next_config_asset,
project_root,
env,
config_asset.map_or(project_root, |c| c.path()),
config_asset.map_or_else(|| AssetIdentVc::from_path(project_root), |c| c.ident()),
context,
intermediate_output_path,
runtime_entries,
Expand Down
9 changes: 4 additions & 5 deletions crates/next-core/src/next_edge/transition.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
use std::collections::HashMap;

use anyhow::{anyhow, bail, Result};
use indexmap::IndexMap;
use turbo_tasks::Value;
use turbo_tasks_fs::{rope::RopeBuilder, File, FileContent, FileContentVc, FileSystemPathVc};
use turbopack::{
Expand Down Expand Up @@ -67,7 +66,7 @@ impl Transition for NextEdgeTransition {
let FileContent::Content(base) = &*self.bootstrap_file.await? else {
bail!("runtime code not found");
};
let path = asset.path().await?;
let path = asset.ident().path().await?;
let path = self
.base_path
.await?
Expand All @@ -93,7 +92,7 @@ impl Transition for NextEdgeTransition {
new_content.concat(base.content());
let file = File::from(new_content.build());
let virtual_asset = VirtualAssetVc::new(
asset.path().join("next-edge-bootstrap.ts"),
asset.ident().path().join("next-edge-bootstrap.ts"),
FileContent::Content(file).cell().into(),
);

Expand All @@ -103,7 +102,7 @@ impl Transition for NextEdgeTransition {
Value::new(EcmascriptModuleAssetType::Typescript),
EcmascriptInputTransformsVc::cell(vec![EcmascriptInputTransform::TypeScript]),
context.compile_time_info(),
InnerAssetsVc::cell(HashMap::from([("ENTRY".to_string(), asset)])),
InnerAssetsVc::cell(IndexMap::from([("ENTRY".to_string(), asset)])),
);

let asset = ChunkGroupFilesAsset {
Expand Down
Loading

0 comments on commit be1352f

Please sign in to comment.