Skip to content

Commit

Permalink
generate the same next/font modules for the same options (vercel#63513)
Browse files Browse the repository at this point in the history
### What?

Improves caching of next/font generated modules (make them independent
on importer context)


Closes PACK-2796
  • Loading branch information
sokra authored Mar 26, 2024
1 parent f4fc687 commit 459e8fe
Show file tree
Hide file tree
Showing 8 changed files with 167 additions and 131 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ struct Fallback {
pub(super) async fn get_font_fallback(
context: Vc<FileSystemPath>,
options_vc: Vc<NextFontGoogleOptions>,
request_hash: Vc<u32>,
request_hash: u32,
) -> Result<Vc<FontFallback>> {
let options = options_vc.await?;
Ok(match &options.fallback {
Expand Down
144 changes: 81 additions & 63 deletions packages/next-swc/crates/next-core/src/next_font/google/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,38 +80,16 @@ impl NextFontGoogleReplacer {
pub fn new(project_path: Vc<FileSystemPath>) -> Vc<Self> {
Self::cell(NextFontGoogleReplacer { project_path })
}
}

#[turbo_tasks::value_impl]
impl ImportMappingReplacement for NextFontGoogleReplacer {
#[turbo_tasks::function]
fn replace(&self, _capture: String) -> Vc<ImportMapping> {
ImportMapping::Ignore.into()
}

/// Intercepts requests for `next/font/google/target.css` and returns a
/// JavaScript object with a generated className from a referenced css
/// module.
#[turbo_tasks::function]
async fn result(
&self,
_context: Vc<FileSystemPath>,
request: Vc<Request>,
) -> Result<Vc<ImportMapResult>> {
let request = &*request.await?;
let Request::Module {
module: _,
path: _,
query: query_vc,
} = request
else {
return Ok(ImportMapResult::NoEntry.into());
};
async fn import_map_result(&self, query: String) -> Result<Vc<ImportMapResult>> {
let request_hash = get_request_hash(&query).await?;
let qstr = qstring::QString::from(query.as_str());
let query_vc = Vc::cell(query);

let font_data = load_font_data(self.project_path);
let query = &*query_vc.await?;
let options = font_options_from_query_map(*query_vc, font_data);
let request_hash = get_request_hash(*query_vc);
let options = font_options_from_query_map(query_vc, font_data);

let fallback = get_font_fallback(self.project_path, options, request_hash);
let properties = get_font_css_properties(options, fallback, request_hash).await?;
let js_asset = VirtualSource::new(
Expand All @@ -136,7 +114,7 @@ impl ImportMappingReplacement for NextFontGoogleReplacer {
export default fontData;
"#,
// Pass along whichever options we received to the css handler
qstring::QString::from(&**query),
qstr,
properties.font_family.await?,
properties
.weight
Expand All @@ -155,62 +133,66 @@ impl ImportMappingReplacement for NextFontGoogleReplacer {
)
.into()),
);

Ok(ImportMapResult::Result(ResolveResult::source(Vc::upcast(js_asset)).into()).into())
}
}

#[turbo_tasks::value(shared)]
pub struct NextFontGoogleCssModuleReplacer {
project_path: Vc<FileSystemPath>,
execution_context: Vc<ExecutionContext>,
}

#[turbo_tasks::value_impl]
impl NextFontGoogleCssModuleReplacer {
#[turbo_tasks::function]
pub fn new(
project_path: Vc<FileSystemPath>,
execution_context: Vc<ExecutionContext>,
) -> Vc<Self> {
Self::cell(NextFontGoogleCssModuleReplacer {
project_path,
execution_context,
})
}
}

#[turbo_tasks::value_impl]
impl ImportMappingReplacement for NextFontGoogleCssModuleReplacer {
impl ImportMappingReplacement for NextFontGoogleReplacer {
#[turbo_tasks::function]
fn replace(&self, _capture: String) -> Vc<ImportMapping> {
ImportMapping::Ignore.into()
}

/// Intercepts requests for the css module made by the virtual JavaScript
/// asset generated by the above replacer. Returns a VirtualSource of a CSS
/// Module containing font face definitions and exporting class names for
/// the font and an optional css variable.
/// Intercepts requests for `next/font/google/target.css` and returns a
/// JavaScript object with a generated className from a referenced css
/// module.
#[turbo_tasks::function]
async fn result(
&self,
self: Vc<Self>,
_context: Vc<FileSystemPath>,
request: Vc<Request>,
) -> Result<Vc<ImportMapResult>> {
let request = &*request.await?;
let Request::Module {
module: _,
path: _,
query: query_vc,
query,
} = request
else {
return Ok(ImportMapResult::NoEntry.into());
};

Ok(self.import_map_result(query.await?.to_string()))
}
}

#[turbo_tasks::value(shared)]
pub struct NextFontGoogleCssModuleReplacer {
project_path: Vc<FileSystemPath>,
execution_context: Vc<ExecutionContext>,
}

#[turbo_tasks::value_impl]
impl NextFontGoogleCssModuleReplacer {
#[turbo_tasks::function]
pub fn new(
project_path: Vc<FileSystemPath>,
execution_context: Vc<ExecutionContext>,
) -> Vc<Self> {
Self::cell(NextFontGoogleCssModuleReplacer {
project_path,
execution_context,
})
}

#[turbo_tasks::function]
async fn import_map_result(&self, query: String) -> Result<Vc<ImportMapResult>> {
let request_hash = get_request_hash(&query).await?;
let query_vc = Vc::cell(query);
let font_data = load_font_data(self.project_path);
let options = font_options_from_query_map(*query_vc, font_data);
let options = font_options_from_query_map(query_vc, font_data);
let stylesheet_url = get_stylesheet_url_from_options(options, font_data);
let request_hash = get_request_hash(*query_vc);
let scoped_font_family = get_scoped_font_family(
FontFamilyType::WebFont.cell(),
options.font_family(),
Expand Down Expand Up @@ -266,12 +248,47 @@ impl ImportMappingReplacement for NextFontGoogleCssModuleReplacer {
)
.into(),
),
);
)
.resolve()
.await?;

println!("css_asset: {:?}, query: {}", css_asset, query_vc.await?);

Ok(ImportMapResult::Result(ResolveResult::source(Vc::upcast(css_asset)).into()).into())
}
}

#[turbo_tasks::value_impl]
impl ImportMappingReplacement for NextFontGoogleCssModuleReplacer {
#[turbo_tasks::function]
fn replace(&self, _capture: String) -> Vc<ImportMapping> {
ImportMapping::Ignore.into()
}

/// Intercepts requests for the css module made by the virtual JavaScript
/// asset generated by the above replacer. Returns a VirtualSource of a CSS
/// Module containing font face definitions and exporting class names for
/// the font and an optional css variable.
#[turbo_tasks::function]
async fn result(
self: Vc<Self>,
_context: Vc<FileSystemPath>,
request: Vc<Request>,
) -> Result<Vc<ImportMapResult>> {
let request = &*request.await?;
let Request::Module {
module: _,
path: _,
query: query_vc,
} = request
else {
return Ok(ImportMapResult::NoEntry.into());
};

Ok(self.import_map_result(query_vc.await?.to_string()))
}
}

#[derive(Clone, Debug, Serialize, Deserialize)]
struct NextFontGoogleFontFileOptions {
pub url: String,
Expand Down Expand Up @@ -489,7 +506,7 @@ async fn get_stylesheet_url_from_options(
async fn get_font_css_properties(
options_vc: Vc<NextFontGoogleOptions>,
font_fallback: Vc<FontFallback>,
request_hash: Vc<u32>,
request_hash: u32,
) -> Result<Vc<FontCssProperties>> {
let options = &*options_vc.await?;
let scoped_font_family = &*get_scoped_font_family(
Expand Down Expand Up @@ -549,8 +566,9 @@ async fn font_options_from_query_map(
bail!("Expected one entry");
};

options_from_request(&parse_json_with_source_context(&json)?, &*font_data.await?)
.map(|o| NextFontGoogleOptions::new(Value::new(o)))
let options =
options_from_request(&parse_json_with_source_context(&json)?, &*font_data.await?)?;
Ok(NextFontGoogleOptions::new(Value::new(options)))
}

async fn font_file_options_from_query_map(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ static BOLD_WEIGHT: f64 = 700.0;
pub(super) async fn get_font_fallbacks(
context: Vc<FileSystemPath>,
options_vc: Vc<NextFontLocalOptions>,
request_hash: Vc<u32>,
request_hash: u32,
) -> Result<Vc<FontFallbacks>> {
let options = &*options_vc.await?;
let mut font_fallbacks = vec![];
Expand Down
Loading

0 comments on commit 459e8fe

Please sign in to comment.