Skip to content

Commit 70984fc

Browse files
committed
enable content hashing in production
1 parent 91cfcb6 commit 70984fc

File tree

4 files changed

+72
-10
lines changed

4 files changed

+72
-10
lines changed

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

+4-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,9 @@ use turbopack::{
1313
},
1414
resolve_options_context::ResolveOptionsContext,
1515
};
16-
use turbopack_browser::{react_refresh::assert_can_resolve_react_refresh, BrowserChunkingContext};
16+
use turbopack_browser::{
17+
react_refresh::assert_can_resolve_react_refresh, BrowserChunkingContext, ContentHashing,
18+
};
1719
use turbopack_core::{
1820
chunk::{
1921
module_id_strategies::ModuleIdStrategy, ChunkingConfig, ChunkingContext, MinifyType,
@@ -483,6 +485,7 @@ pub async fn get_client_chunking_context(
483485
..Default::default()
484486
},
485487
);
488+
builder = builder.use_content_hashing(ContentHashing::Direct { length: 16 })
486489
}
487490

488491
Ok(Vc::upcast(builder.build()))

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

+65-7
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,15 @@
11
use anyhow::{bail, Context, Result};
2+
use serde::{Deserialize, Serialize};
23
use tracing::Instrument;
34
use turbo_rcstr::RcStr;
4-
use turbo_tasks::{ResolvedVc, TryJoinIterExt, Upcast, Value, ValueToString, Vc};
5+
use turbo_tasks::{
6+
trace::TraceRawVcs, NonLocalValue, ResolvedVc, TaskInput, TryJoinIterExt, Upcast, Value,
7+
ValueToString, Vc,
8+
};
59
use turbo_tasks_fs::FileSystemPath;
10+
use turbo_tasks_hash::{hash_xxh3_hash64, DeterministicHash};
611
use turbopack_core::{
7-
asset::Asset,
12+
asset::{Asset, AssetContent},
813
chunk::{
914
availability_info::AvailabilityInfo,
1015
chunk_group::{make_chunk_group, MakeChunkGroupResult},
@@ -32,6 +37,31 @@ use crate::ecmascript::{
3237
list::asset::{EcmascriptDevChunkList, EcmascriptDevChunkListSource},
3338
};
3439

40+
#[derive(
41+
Debug,
42+
TaskInput,
43+
Clone,
44+
Copy,
45+
PartialEq,
46+
Eq,
47+
Hash,
48+
Serialize,
49+
Deserialize,
50+
TraceRawVcs,
51+
DeterministicHash,
52+
NonLocalValue,
53+
)]
54+
pub enum ContentHashing {
55+
/// Direct content hashing: Embeds the chunk content hash directly into the referencing chunk.
56+
/// Benefit: No hash manifest needed.
57+
/// Downside: Causes cascading hash invalidation.
58+
Direct {
59+
/// The length of the content hash in hex chars. Anything lower than 8 is not recommended
60+
/// due to the high risk of collisions.
61+
length: u8,
62+
},
63+
}
64+
3565
pub struct BrowserChunkingContextBuilder {
3666
chunking_context: BrowserChunkingContext,
3767
}
@@ -110,6 +140,11 @@ impl BrowserChunkingContextBuilder {
110140
self
111141
}
112142

143+
pub fn use_content_hashing(mut self, content_hashing: ContentHashing) -> Self {
144+
self.chunking_context.content_hashing = Some(content_hashing);
145+
self
146+
}
147+
113148
pub fn build(self) -> Vc<BrowserChunkingContext> {
114149
BrowserChunkingContext::new(Value::new(self.chunking_context))
115150
}
@@ -158,6 +193,8 @@ pub struct BrowserChunkingContext {
158193
runtime_type: RuntimeType,
159194
/// Whether to minify resulting chunks
160195
minify_type: MinifyType,
196+
/// Whether content hashing is enabled.
197+
content_hashing: Option<ContentHashing>,
161198
/// Whether to generate source maps
162199
source_maps_type: SourceMapsType,
163200
/// Whether to use manifest chunks for lazy compilation
@@ -197,6 +234,7 @@ impl BrowserChunkingContext {
197234
environment,
198235
runtime_type,
199236
minify_type: MinifyType::NoMinify,
237+
content_hashing: None,
200238
source_maps_type: SourceMapsType::Full,
201239
manifest_chunks: false,
202240
module_id_strategy: ResolvedVc::upcast(DevModuleIdStrategy::new_resolved()),
@@ -338,15 +376,35 @@ impl ChunkingContext for BrowserChunkingContext {
338376
#[turbo_tasks::function]
339377
async fn chunk_path(
340378
&self,
341-
_asset: Option<Vc<Box<dyn Asset>>>,
379+
asset: Option<Vc<Box<dyn Asset>>>,
342380
ident: Vc<AssetIdent>,
343381
extension: RcStr,
344382
) -> Result<Vc<FileSystemPath>> {
345383
let root_path = self.chunk_root_path;
346-
let name = ident
347-
.output_name(*self.root_path, extension)
348-
.owned()
349-
.await?;
384+
let name = match self.content_hashing {
385+
None => {
386+
ident
387+
.output_name(*self.root_path, extension)
388+
.owned()
389+
.await?
390+
}
391+
Some(ContentHashing::Direct { length }) => {
392+
let Some(asset) = asset else {
393+
bail!("chunk_path requires an asset when content hashing is enabled");
394+
};
395+
let content = asset.content().await?;
396+
if let AssetContent::File(file) = &*content {
397+
let hash = hash_xxh3_hash64(&file.await?);
398+
let length = length as usize;
399+
format!("{hash:0length$x}{extension}").into()
400+
} else {
401+
bail!(
402+
"chunk_path requires an asset with file content when content hashing is \
403+
enabled"
404+
);
405+
}
406+
}
407+
};
350408
Ok(root_path.join(name))
351409
}
352410

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ pub(crate) mod chunking_context;
77
pub mod ecmascript;
88
pub mod react_refresh;
99

10-
pub use chunking_context::{BrowserChunkingContext, BrowserChunkingContextBuilder};
10+
pub use chunking_context::{BrowserChunkingContext, BrowserChunkingContextBuilder, ContentHashing};
1111

1212
pub fn register() {
1313
turbo_tasks::register();

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

+2-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ use turbopack::{
2121
css::chunk::CssChunkType, ecmascript::chunk::EcmascriptChunkType,
2222
global_module_ids::get_global_module_id_strategy,
2323
};
24-
use turbopack_browser::BrowserChunkingContext;
24+
use turbopack_browser::{BrowserChunkingContext, ContentHashing};
2525
use turbopack_cli_utils::issue::{ConsoleUi, LogOptions};
2626
use turbopack_core::{
2727
asset::Asset,
@@ -354,6 +354,7 @@ async fn build_internal(
354354
..Default::default()
355355
},
356356
);
357+
builder = builder.use_content_hashing(ContentHashing::Direct { length: 16 })
357358
}
358359
}
359360

0 commit comments

Comments
 (0)