-
Notifications
You must be signed in to change notification settings - Fork 27.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
use structured images with metainfo (blur placeholder) (#48531)
### What? add support for blur placeholder generation to turbopack add `StructuredImageModuleType` which is used with `ModuleType::Custom` to allow importing an image as `{ url, width, height, blurDataURL, blurWidth, blurHeight }` in contrast to next.js with webpack this will also generate blur placeholder in development instead of using a _next/image reference. This should lead to more production-like experience (at the cost of a little bit of compilation time). turbo PR: vercel/turborepo#4621 ### Why? Turbopack was crashing on `placeholder="blur"` before. fixes WEB-534 ### Turbopack changes * vercel/turborepo#4521 <!-- OJ Kwon - feat(contextcondition): support InPath contextcondition --> * vercel/turborepo#4601 <!-- Alex Kirszenberg - Chunking Context Refactor pt. 3: Address PR comments from pt. 2 --> * vercel/turborepo#4623 <!-- Tobias Koppers - exclude turborepo from turbopack bench tests --> * vercel/turborepo#4399 <!-- Leah - support require.context --> * vercel/turborepo#4610 <!-- OJ Kwon - test(subset): add mdx test into subset --> * vercel/turborepo#4624 <!-- Tobias Koppers - run benchmarks on windows and macOS too --> * vercel/turborepo#4620 <!-- Alex Kirszenberg - Make ContainmentTree fully generic --> * vercel/turborepo#4600 <!-- Tobias Koppers - add getChunkPath method --> * vercel/turborepo#4621 <!-- Tobias Koppers - add turbopack-image --> * vercel/turborepo#4639 <!-- Tobias Koppers - restrict snapshot path for windows path length limit --> * vercel/turborepo#4641 <!-- Tobias Koppers - put webp behind a feature flag -->
- Loading branch information
Showing
29 changed files
with
498 additions
and
70 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
use anyhow::Result; | ||
use indexmap::indexmap; | ||
use turbo_binding::{ | ||
turbo::tasks::Value, | ||
turbopack::{ | ||
core::{ | ||
asset::AssetVc, | ||
context::{AssetContext, AssetContextVc}, | ||
plugin::{CustomModuleType, CustomModuleTypeVc}, | ||
resolve::ModulePartVc, | ||
}, | ||
ecmascript::{ | ||
EcmascriptInputTransformsVc, EcmascriptModuleAssetType, EcmascriptModuleAssetVc, | ||
EcmascriptOptions, InnerAssetsVc, | ||
}, | ||
r#static::StaticModuleAssetVc, | ||
}, | ||
}; | ||
|
||
use self::source::StructuredImageSourceAsset; | ||
|
||
pub(crate) mod source; | ||
|
||
/// Module type that analyzes images and offers some meta information like | ||
/// width, height and blur placeholder as export from the module. | ||
#[turbo_tasks::value] | ||
pub struct StructuredImageModuleType {} | ||
|
||
#[turbo_tasks::value_impl] | ||
impl StructuredImageModuleTypeVc { | ||
#[turbo_tasks::function] | ||
pub fn new() -> Self { | ||
StructuredImageModuleTypeVc::cell(StructuredImageModuleType {}) | ||
} | ||
} | ||
|
||
#[turbo_tasks::value_impl] | ||
impl CustomModuleType for StructuredImageModuleType { | ||
#[turbo_tasks::function] | ||
async fn create_module( | ||
&self, | ||
source: AssetVc, | ||
context: AssetContextVc, | ||
_part: Option<ModulePartVc>, | ||
) -> Result<AssetVc> { | ||
let static_asset = StaticModuleAssetVc::new(source, context); | ||
Ok(EcmascriptModuleAssetVc::new_with_inner_assets( | ||
StructuredImageSourceAsset { image: source }.cell().into(), | ||
context, | ||
Value::new(EcmascriptModuleAssetType::Ecmascript), | ||
EcmascriptInputTransformsVc::empty(), | ||
Value::new(EcmascriptOptions { | ||
..Default::default() | ||
}), | ||
context.compile_time_info(), | ||
InnerAssetsVc::cell(indexmap!( | ||
"IMAGE".to_string() => static_asset.into() | ||
)), | ||
) | ||
.into()) | ||
} | ||
} |
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,81 @@ | ||
use std::io::Write; | ||
|
||
use anyhow::{bail, Result}; | ||
use serde::Serialize; | ||
use turbo_binding::{ | ||
turbo::{ | ||
tasks::primitives::StringVc, | ||
tasks_fs::{rope::RopeBuilder, FileContent}, | ||
}, | ||
turbopack::{ | ||
core::{ | ||
asset::{Asset, AssetContent, AssetContentVc, AssetVc}, | ||
ident::AssetIdentVc, | ||
}, | ||
ecmascript::utils::StringifyJs, | ||
image::process::{get_meta_data, BlurPlaceholderOptions, BlurPlaceholderOptionsVc}, | ||
}, | ||
}; | ||
|
||
fn modifier() -> StringVc { | ||
StringVc::cell("structured image object".to_string()) | ||
} | ||
|
||
#[turbo_tasks::function] | ||
fn blur_options() -> BlurPlaceholderOptionsVc { | ||
BlurPlaceholderOptions { | ||
quality: 70, | ||
size: 8, | ||
} | ||
.cell() | ||
} | ||
|
||
#[derive(Serialize)] | ||
#[serde(rename_all = "camelCase")] | ||
pub struct ImageExport<'a> { | ||
width: u32, | ||
height: u32, | ||
#[serde(rename = "blurDataURL")] | ||
blur_data_url: Option<&'a str>, | ||
blur_width: u32, | ||
blur_height: u32, | ||
} | ||
|
||
/// An source asset that transforms an image into javascript code which exports | ||
/// an object with meta information like width, height and a blur placeholder. | ||
#[turbo_tasks::value(shared)] | ||
pub struct StructuredImageSourceAsset { | ||
pub image: AssetVc, | ||
} | ||
|
||
#[turbo_tasks::value_impl] | ||
impl Asset for StructuredImageSourceAsset { | ||
#[turbo_tasks::function] | ||
fn ident(&self) -> AssetIdentVc { | ||
self.image.ident().with_modifier(modifier()) | ||
} | ||
|
||
#[turbo_tasks::function] | ||
async fn content(&self) -> Result<AssetContentVc> { | ||
let content = self.image.content().await?; | ||
let AssetContent::File(content) = *content else { | ||
bail!("Input source is not a file and can't be transformed into image information"); | ||
}; | ||
let mut result = RopeBuilder::from(""); | ||
let info = get_meta_data(self.image.ident(), content, Some(blur_options())).await?; | ||
let info = ImageExport { | ||
width: info.width, | ||
height: info.height, | ||
blur_width: info.blur_placeholder.as_ref().map_or(0, |p| p.width), | ||
blur_height: info.blur_placeholder.as_ref().map_or(0, |p| p.height), | ||
blur_data_url: info.blur_placeholder.as_ref().map(|p| p.data_url.as_str()), | ||
}; | ||
writeln!(result, "import src from \"IMAGE\";",)?; | ||
writeln!( | ||
result, | ||
"export default {{ src, ...{} }}", | ||
StringifyJs(&info) | ||
)?; | ||
Ok(AssetContent::File(FileContent::Content(result.build().into()).cell()).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
File renamed without changes.
File renamed without changes.
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
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
21 changes: 21 additions & 0 deletions
21
...xt-dev-tests/tests/integration/next/image/basic/issues/Processing image failed-376140.txt
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,21 @@ | ||
PlainIssue { | ||
severity: Error, | ||
context: "[project]/packages/next-swc/crates/next-dev-tests/tests/integration/next/image/basic/input/public/broken.jpeg", | ||
category: "image", | ||
title: "Processing image failed", | ||
description: "unable to decode image data\n\nCaused by:\n- The image format could not be determined", | ||
detail: "", | ||
documentation_link: "", | ||
source: None, | ||
sub_issues: [], | ||
processing_path: Some( | ||
[ | ||
PlainIssueProcessingPathItem { | ||
context: Some( | ||
"[project]/packages/next-swc/crates/next-dev-tests/tests/integration/next/image/basic/input/pages/index.js", | ||
), | ||
description: "Next.js pages directory", | ||
}, | ||
], | ||
), | ||
} |
File renamed without changes.
File renamed without changes.
File renamed without changes.
28 changes: 28 additions & 0 deletions
28
...ipped__/context-weak/issues/error TP1007 require.context(__quo__.__quo__, fals-7a04ec.txt
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,28 @@ | ||
PlainIssue { | ||
severity: Error, | ||
context: "[project]/packages/next-swc/crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/context-weak/input/index.js", | ||
category: "parse", | ||
title: "error TP1007 require.context(\".\", false, /.+/, \"weak\") is not statically analyze-able: require.context() only supports 1-3 arguments (mode is not supported)", | ||
description: "", | ||
detail: "", | ||
documentation_link: "", | ||
source: Some( | ||
PlainIssueSource { | ||
asset: PlainAsset { | ||
ident: "[project]/packages/next-swc/crates/next-dev-tests/tests/integration/webpack/chunks/__skipped__/context-weak/input/index.js", | ||
}, | ||
start: SourcePos { | ||
line: 19, | ||
column: 23, | ||
}, | ||
end: SourcePos { | ||
line: 19, | ||
column: 23, | ||
}, | ||
}, | ||
), | ||
sub_issues: [], | ||
processing_path: Some( | ||
[], | ||
), | ||
} |
Oops, something went wrong.