From c2c267222cb67da9b4e190efdedcff5f40fddfb4 Mon Sep 17 00:00:00 2001 From: ClarkXia Date: Thu, 23 Nov 2023 10:13:31 +0800 Subject: [PATCH] feat: plugin for generate assets manifest (#5) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: plugin for generate assets manifest * fix: camel case --------- Co-authored-by: 鲲尘 --- crates/plugin_manifest/Cargo.toml | 3 + crates/plugin_manifest/src/plugin.rs | 87 ++++++++++++++----- crates/plugin_manifest/tests/fixtures.rs | 2 +- .../tests/fixtures/with-assets/a.js | 1 + .../tests/fixtures/with-assets/b.js | 1 + .../tests/fixtures/with-assets/img.png | 0 .../tests/fixtures/with-assets/index.js | 5 ++ .../fixtures/with-assets/snapshot/output.snap | 4 + .../fixtures/with-assets/test.config.json | 13 +++ 9 files changed, 95 insertions(+), 21 deletions(-) create mode 100644 crates/plugin_manifest/tests/fixtures/with-assets/a.js create mode 100644 crates/plugin_manifest/tests/fixtures/with-assets/b.js create mode 100644 crates/plugin_manifest/tests/fixtures/with-assets/img.png create mode 100644 crates/plugin_manifest/tests/fixtures/with-assets/index.js create mode 100644 crates/plugin_manifest/tests/fixtures/with-assets/snapshot/output.snap create mode 100644 crates/plugin_manifest/tests/fixtures/with-assets/test.config.json diff --git a/crates/plugin_manifest/Cargo.toml b/crates/plugin_manifest/Cargo.toml index f9525ff..9ad22a5 100644 --- a/crates/plugin_manifest/Cargo.toml +++ b/crates/plugin_manifest/Cargo.toml @@ -8,6 +8,9 @@ edition = "2021" [dependencies] async-trait = { workspace = true } tracing = { workspace = true } +regex = { workspace = true } +serde = { workspace = true, features = ["derive"] } +serde_json = { workspace = true } rspack_core = { path = "../.rspack_crates/rspack_core" } rspack_error = { path = "../.rspack_crates/rspack_error" } diff --git a/crates/plugin_manifest/src/plugin.rs b/crates/plugin_manifest/src/plugin.rs index e89bfac..8bbde27 100644 --- a/crates/plugin_manifest/src/plugin.rs +++ b/crates/plugin_manifest/src/plugin.rs @@ -1,6 +1,9 @@ +use std::collections::HashMap; +use serde::{Serialize, Deserialize}; + use rspack_core::{ Plugin,PluginContext, PluginProcessAssetsOutput,ProcessAssetsArgs, - CompilationAsset, + CompilationAsset, PublicPath, rspack_sources::{RawSource, SourceExt}, }; // use rspack_error::Result; @@ -8,16 +11,23 @@ use rspack_core::{ #[derive(Debug)] pub struct ManifestPlugin; + +#[derive(Debug, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct AssetsManifest { + pub pages: HashMap>, + pub entries: HashMap>, + pub public_path: String, +} + +const AUTO_PUBLIC_PATH_PLACEHOLDER: &str = "__RSPACK_PLUGIN_CSS_AUTO_PUBLIC_PATH__"; + impl ManifestPlugin { pub fn new() -> Self { Self {} } } -fn default_cotent() -> &'static str { - r#"{"assets": []}"# -} - #[async_trait::async_trait] impl Plugin for ManifestPlugin { fn name(&self) -> &'static str { @@ -30,29 +40,66 @@ impl Plugin for ManifestPlugin { args: ProcessAssetsArgs<'_>, )-> PluginProcessAssetsOutput { let compilation = args.compilation; + let public_path = match &compilation.options.output.public_path { + PublicPath::String(p) => p, + PublicPath::Auto => AUTO_PUBLIC_PATH_PLACEHOLDER, + }; + let mut assets_mainfest = AssetsManifest { + pages: HashMap::new(), + entries: HashMap::new(), + public_path: public_path.to_string(), + }; let entry_points = &compilation.entrypoints; - println!("entry_points: {:?}", entry_points); - Ok(()) - } - - async fn process_assets_stage_optimize_inline( - &self, - _ctx: PluginContext, - args: ProcessAssetsArgs<'_>, - ) -> PluginProcessAssetsOutput { - let compilation = args.compilation; - + let assets = &compilation.assets(); + + entry_points.iter().for_each(|(name, _entry)| { + let mut files: Vec = Vec::new(); + compilation.entrypoint_by_name(name).chunks.iter().for_each(|chunk| { + + if let Some(chunk) = compilation.chunk_by_ukey.get(chunk) { + chunk.files.iter().for_each(|file| { + if let Some(asset) = assets.get(file) { + if !asset.info.hot_module_replacement && !asset.info.development { + files.push(file.to_string()); + } + } else { + files.push(file.to_string()); + } + }); + }; + }); + assets_mainfest.entries.insert(name.to_string(), files); + }); + let page_chunk_name_regex = regex::Regex::new(r"^p_").unwrap(); + compilation + .chunk_by_ukey + .values() + .for_each(|c| { + if let Some(name) = &c.id { + if !c.has_entry_module(&compilation.chunk_graph) && !c.can_be_initial(&compilation.chunk_group_by_ukey) { + assets_mainfest.pages.insert( + page_chunk_name_regex.replace(name, "").to_string(), + Vec::from_iter( + c.files + .iter() + // Only collect js and css files. + .filter(|f| f.ends_with(".js") || f.ends_with(".css")) + .cloned() + ), + ); + } + } + }); + let json_string = serde_json::to_string(&assets_mainfest).unwrap(); let output_path = compilation .options .output .path - .join("manifest.json".to_string()).to_string_lossy().to_string(); - println!("output_path: {}", output_path); + .join("assets-manifest.json".to_string()).to_string_lossy().to_string(); compilation.emit_asset( output_path, - CompilationAsset::from(RawSource::from(default_cotent().to_owned()).boxed()), + CompilationAsset::from(RawSource::from(json_string).boxed()), ); - Ok(()) } } diff --git a/crates/plugin_manifest/tests/fixtures.rs b/crates/plugin_manifest/tests/fixtures.rs index d28f36b..c415eb3 100644 --- a/crates/plugin_manifest/tests/fixtures.rs +++ b/crates/plugin_manifest/tests/fixtures.rs @@ -3,7 +3,7 @@ use rspack_core::PluginExt; use rspack_testing::{fixture,test_fixture_insta}; use plugin_manifest::ManifestPlugin; -#[fixture("tests/fixtures/*")] +#[fixture("tests/fixtures/with-assets")] fn manifest(fixture_path: PathBuf) { test_fixture_insta( &fixture_path, diff --git a/crates/plugin_manifest/tests/fixtures/with-assets/a.js b/crates/plugin_manifest/tests/fixtures/with-assets/a.js new file mode 100644 index 0000000..0d4c247 --- /dev/null +++ b/crates/plugin_manifest/tests/fixtures/with-assets/a.js @@ -0,0 +1 @@ +console.log('a.js'); \ No newline at end of file diff --git a/crates/plugin_manifest/tests/fixtures/with-assets/b.js b/crates/plugin_manifest/tests/fixtures/with-assets/b.js new file mode 100644 index 0000000..50715a5 --- /dev/null +++ b/crates/plugin_manifest/tests/fixtures/with-assets/b.js @@ -0,0 +1 @@ +console.log('b.js'); \ No newline at end of file diff --git a/crates/plugin_manifest/tests/fixtures/with-assets/img.png b/crates/plugin_manifest/tests/fixtures/with-assets/img.png new file mode 100644 index 0000000..e69de29 diff --git a/crates/plugin_manifest/tests/fixtures/with-assets/index.js b/crates/plugin_manifest/tests/fixtures/with-assets/index.js new file mode 100644 index 0000000..336f6d0 --- /dev/null +++ b/crates/plugin_manifest/tests/fixtures/with-assets/index.js @@ -0,0 +1,5 @@ +import url from './img.png'; + +import('./a.js'); +import('./b.js'); +console.log('url', url); diff --git a/crates/plugin_manifest/tests/fixtures/with-assets/snapshot/output.snap b/crates/plugin_manifest/tests/fixtures/with-assets/snapshot/output.snap new file mode 100644 index 0000000..775c9ee --- /dev/null +++ b/crates/plugin_manifest/tests/fixtures/with-assets/snapshot/output.snap @@ -0,0 +1,4 @@ +--- +source: crates/.rspack_crates/rspack_testing/src/run_fixture.rs +--- + diff --git a/crates/plugin_manifest/tests/fixtures/with-assets/test.config.json b/crates/plugin_manifest/tests/fixtures/with-assets/test.config.json new file mode 100644 index 0000000..50bee5b --- /dev/null +++ b/crates/plugin_manifest/tests/fixtures/with-assets/test.config.json @@ -0,0 +1,13 @@ +{ + "module": { + "rules": [ + { + "test": { + "type": "regexp", + "matcher": "\\.png$" + }, + "type": "asset/resource" + } + ] + } +} \ No newline at end of file