-
Notifications
You must be signed in to change notification settings - Fork 27k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Turbopack: allow specified AssetIdents for naming chunk groups (#68917)
Previously, in a number of situations, we would implicitly use the entry module’s ident to name the chunk group. This adds the ability to specify a different name. Now, for evaluated chunk groups for pages, we use the page source’s ident. This prevents changes in loader chunk groups from changing the chunk name, which breaks HMR. We still use the entry module’s ident for most other cases now, but it is now explicitly provided. Test Plan: `TURBOPACK=1 pnpm test-dev test/development/acceptance/ReactRefreshModule.test.ts` with #68698 applied --------- Co-authored-by: Tobias Koppers <[email protected]>
- Loading branch information
1 parent
f9148a2
commit fcde8fc
Showing
48 changed files
with
303 additions
and
69 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,216 @@ | ||
use std::io::Write; | ||
|
||
use anyhow::Result; | ||
use turbo_tasks::{RcStr, ValueToString, Vc}; | ||
use turbo_tasks_fs::{glob::Glob, rope::RopeBuilder}; | ||
use turbopack_core::{ | ||
asset::{Asset, AssetContent}, | ||
chunk::{ | ||
ChunkItem, ChunkType, ChunkableModule, ChunkableModuleReference, ChunkingContext, | ||
EvaluatableAsset, | ||
}, | ||
ident::AssetIdent, | ||
module::Module, | ||
reference::{ModuleReference, ModuleReferences}, | ||
resolve::ModuleResolveResult, | ||
}; | ||
use turbopack_ecmascript::{ | ||
chunk::{ | ||
EcmascriptChunkItem, EcmascriptChunkItemContent, EcmascriptChunkItemOptions, | ||
EcmascriptChunkPlaceable, EcmascriptChunkType, EcmascriptExports, | ||
}, | ||
utils::StringifyJs, | ||
}; | ||
|
||
#[turbo_tasks::function] | ||
fn modifier() -> Vc<RcStr> { | ||
Vc::cell("hmr-entry".into()) | ||
} | ||
|
||
#[turbo_tasks::value(shared)] | ||
pub struct HmrEntryModule { | ||
pub ident: Vc<AssetIdent>, | ||
pub module: Vc<Box<dyn ChunkableModule>>, | ||
pub force_reload: bool, | ||
} | ||
|
||
#[turbo_tasks::value_impl] | ||
impl HmrEntryModule { | ||
#[turbo_tasks::function] | ||
pub fn new( | ||
ident: Vc<AssetIdent>, | ||
module: Vc<Box<dyn ChunkableModule>>, | ||
force_reload: bool, | ||
) -> Vc<Self> { | ||
Self { | ||
ident, | ||
module, | ||
force_reload, | ||
} | ||
.cell() | ||
} | ||
} | ||
|
||
#[turbo_tasks::value_impl] | ||
impl Module for HmrEntryModule { | ||
#[turbo_tasks::function] | ||
fn ident(&self) -> Vc<AssetIdent> { | ||
self.ident.with_modifier(modifier()) | ||
} | ||
|
||
#[turbo_tasks::function] | ||
fn references(&self) -> Vc<ModuleReferences> { | ||
Vc::cell(vec![Vc::upcast(HmrEntryModuleReference::new(Vc::upcast( | ||
self.module, | ||
)))]) | ||
} | ||
} | ||
|
||
#[turbo_tasks::value_impl] | ||
impl ChunkableModule for HmrEntryModule { | ||
#[turbo_tasks::function] | ||
fn as_chunk_item( | ||
self: Vc<Self>, | ||
chunking_context: Vc<Box<dyn ChunkingContext>>, | ||
) -> Vc<Box<dyn ChunkItem>> { | ||
Vc::upcast( | ||
HmrEntryChunkItem { | ||
module: self, | ||
chunking_context, | ||
} | ||
.cell(), | ||
) | ||
} | ||
} | ||
|
||
#[turbo_tasks::value_impl] | ||
impl Asset for HmrEntryModule { | ||
#[turbo_tasks::function] | ||
fn content(self: Vc<Self>) -> Vc<AssetContent> { | ||
todo!("HmrEntryModule doesn't implement content()") | ||
} | ||
} | ||
|
||
#[turbo_tasks::value_impl] | ||
impl EcmascriptChunkPlaceable for HmrEntryModule { | ||
#[turbo_tasks::function] | ||
fn get_exports(self: Vc<Self>) -> Vc<EcmascriptExports> { | ||
EcmascriptExports::None.cell() | ||
} | ||
|
||
#[turbo_tasks::function] | ||
fn is_marked_as_side_effect_free(self: Vc<Self>, _: Vc<Glob>) -> Vc<bool> { | ||
Vc::cell(false) | ||
} | ||
} | ||
|
||
#[turbo_tasks::value_impl] | ||
impl EvaluatableAsset for HmrEntryModule {} | ||
|
||
#[turbo_tasks::value] | ||
pub struct HmrEntryModuleReference { | ||
pub module: Vc<Box<dyn Module>>, | ||
} | ||
|
||
#[turbo_tasks::value_impl] | ||
impl HmrEntryModuleReference { | ||
#[turbo_tasks::function] | ||
pub fn new(module: Vc<Box<dyn Module>>) -> Vc<Self> { | ||
HmrEntryModuleReference { module }.cell() | ||
} | ||
} | ||
|
||
#[turbo_tasks::value_impl] | ||
impl ValueToString for HmrEntryModuleReference { | ||
#[turbo_tasks::function] | ||
fn to_string(&self) -> Vc<RcStr> { | ||
Vc::cell("entry".into()) | ||
} | ||
} | ||
|
||
#[turbo_tasks::value_impl] | ||
impl ModuleReference for HmrEntryModuleReference { | ||
#[turbo_tasks::function] | ||
async fn resolve_reference(&self) -> Result<Vc<ModuleResolveResult>> { | ||
Ok(ModuleResolveResult::module(self.module).cell()) | ||
} | ||
} | ||
|
||
#[turbo_tasks::value_impl] | ||
impl ChunkableModuleReference for HmrEntryModuleReference {} | ||
|
||
/// The chunk item for [`HmrEntryModule`]. | ||
#[turbo_tasks::value] | ||
struct HmrEntryChunkItem { | ||
module: Vc<HmrEntryModule>, | ||
chunking_context: Vc<Box<dyn ChunkingContext>>, | ||
} | ||
|
||
#[turbo_tasks::value_impl] | ||
impl ChunkItem for HmrEntryChunkItem { | ||
#[turbo_tasks::function] | ||
fn chunking_context(&self) -> Vc<Box<dyn ChunkingContext>> { | ||
Vc::upcast(self.chunking_context) | ||
} | ||
|
||
#[turbo_tasks::function] | ||
fn asset_ident(&self) -> Vc<AssetIdent> { | ||
self.module.ident() | ||
} | ||
|
||
#[turbo_tasks::function] | ||
fn references(&self) -> Vc<ModuleReferences> { | ||
self.module.references() | ||
} | ||
|
||
#[turbo_tasks::function] | ||
fn ty(&self) -> Vc<Box<dyn ChunkType>> { | ||
Vc::upcast(Vc::<EcmascriptChunkType>::default()) | ||
} | ||
|
||
#[turbo_tasks::function] | ||
fn module(&self) -> Vc<Box<dyn Module>> { | ||
Vc::upcast(self.module) | ||
} | ||
} | ||
|
||
#[turbo_tasks::value_impl] | ||
impl EcmascriptChunkItem for HmrEntryChunkItem { | ||
#[turbo_tasks::function] | ||
fn chunking_context(&self) -> Vc<Box<dyn ChunkingContext>> { | ||
self.chunking_context | ||
} | ||
|
||
#[turbo_tasks::function] | ||
async fn content(&self) -> Result<Vc<EcmascriptChunkItemContent>> { | ||
let this = self.module.await?; | ||
let module = this.module; | ||
let chunk_item = module.as_chunk_item(self.chunking_context); | ||
let id = self.chunking_context.chunk_item_id(chunk_item).await?; | ||
|
||
let mut code = RopeBuilder::default(); | ||
if this.force_reload { | ||
writeln!( | ||
code, | ||
"__turbopack_require__({});\nmodule.hot.dispose(() => window.location.reload());", | ||
StringifyJs(&id) | ||
)?; | ||
} else { | ||
writeln!( | ||
code, | ||
"__turbopack_require__({});\nmodule.hot.accept();", | ||
StringifyJs(&id) | ||
)?; | ||
} | ||
Ok(EcmascriptChunkItemContent { | ||
inner_code: code.build(), | ||
options: EcmascriptChunkItemOptions { | ||
strict: true, | ||
module: true, | ||
..Default::default() | ||
}, | ||
..Default::default() | ||
} | ||
.cell()) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.