From d6357a18d60543af66e1d6215867d2d29fe18e88 Mon Sep 17 00:00:00 2001 From: hulxv Date: Fri, 6 Sep 2024 16:09:58 +0300 Subject: [PATCH] refactor: move web-bundler to a stand-alone crate called `metassr-bundler` --- Cargo.lock | 17 ++- Cargo.toml | 3 +- crates/metassr-build/Cargo.toml | 1 + crates/metassr-build/src/bundler.rs | 101 ------------------ crates/metassr-build/src/client/mod.rs | 12 ++- crates/metassr-build/src/server/mod.rs | 7 +- .../metassr-build/src/server/renderer/head.rs | 9 +- crates/metassr-bundler/Cargo.toml | 13 +++ .../scripts => metassr-bundler/src}/bundle.js | 0 crates/metassr-bundler/src/lib.rs | 98 +++++++++++++++++ 10 files changed, 145 insertions(+), 116 deletions(-) create mode 100644 crates/metassr-bundler/Cargo.toml rename crates/{metassr-build/src/scripts => metassr-bundler/src}/bundle.js (100%) create mode 100644 crates/metassr-bundler/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index 117138d..fffec3d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -580,6 +580,7 @@ dependencies = [ "logger", "metacall", "metassr-build", + "metassr-bundler", "metassr-create", "metassr-server", "metassr-utils", @@ -603,11 +604,23 @@ dependencies = [ "html-generator", "lazy_static", "metacall", + "metassr-bundler", "metassr-utils", "serde", "serde_json", ] +[[package]] +name = "metassr-bundler" +version = "0.1.0" +dependencies = [ + "anyhow", + "lazy_static", + "metacall", + "metassr-utils", + "serde_json", +] + [[package]] name = "metassr-cli" version = "0.1.0-alpha" @@ -942,9 +955,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.122" +version = "1.0.128" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "784b6203951c57ff748476b126ccb5e8e2959a5c19e5c617ab1956be3dbc68da" +checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8" dependencies = [ "itoa", "memchr", diff --git a/Cargo.toml b/Cargo.toml index 5d70b39..d571595 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -31,6 +31,7 @@ serde = "1.0.207" tower-layer = "0.3.3" tower-service = "0.3.3" metassr-create = { version = "0.1.0", path = "crates/metassr-create" } +metassr-bundler = { version = "0.1.0", path = "crates/metassr-bundler" } [workspace] members = [ @@ -40,7 +41,7 @@ members = [ "crates/metassr-utils", "crates/html-generator", "metassr-cli", - "crates/metassr-create", + "crates/metassr-create", "crates/metassr-bundler", ] [[bin]] diff --git a/crates/metassr-build/Cargo.toml b/crates/metassr-build/Cargo.toml index 0e15146..7747390 100644 --- a/crates/metassr-build/Cargo.toml +++ b/crates/metassr-build/Cargo.toml @@ -13,3 +13,4 @@ metassr-utils = { version = "0.1.0", path = "../metassr-utils" } html-generator = { path = "../html-generator" } lazy_static = "1.5.0" serde = { version = "1.0.207", features = ["derive"] } +metassr-bundler = { version = "0.1.0", path = "../metassr-bundler" } diff --git a/crates/metassr-build/src/bundler.rs b/crates/metassr-build/src/bundler.rs index 2d4efc0..e69de29 100644 --- a/crates/metassr-build/src/bundler.rs +++ b/crates/metassr-build/src/bundler.rs @@ -1,101 +0,0 @@ -use anyhow::{anyhow, Result}; -use lazy_static::lazy_static; -use metacall::{loaders, metacall, MetacallNull}; -use std::{collections::HashMap, ffi::OsStr, marker::Sized, path::Path, sync::Mutex}; - -use crate::traits::Exec; -lazy_static! { - static ref IS_BUNDLING_SCRIPT_LOADED: Mutex = - Mutex::new(BundleSciptLoadingState::new()); -} -static BUILD_SCRIPT: &str = include_str!("./scripts/bundle.js"); -const BUNDLING_FUNC: &str = "web_bundling"; - -/// A detector for if the bundling script `./scripts/bundle.js` is loaded or not. -#[derive(Debug)] -pub struct BundleSciptLoadingState(bool); - -impl BundleSciptLoadingState { - pub fn new() -> Self { - Self(false) - } - pub fn loaded(&mut self) { - self.0 = true - } - pub fn is_loaded(&self) -> bool { - self.0 - } -} - -impl Default for BundleSciptLoadingState { - fn default() -> Self { - Self::new() - } -} - -#[derive(Debug)] - -pub struct WebBundler<'a> { - pub targets: HashMap, - pub dist_path: &'a Path, -} - -impl<'a> WebBundler<'a> { - pub fn new(targets: &'a HashMap, dist_path: &'a S) -> Self - where - S: AsRef + ?Sized, - { - let targets: HashMap = targets - .iter() - .map(|(k, v)| (k.into(), Path::new(v))) - .collect(); - - Self { - targets, - dist_path: Path::new(dist_path), - } - } -} - -impl<'a> Exec for WebBundler<'a> { - type Output = (); - fn exec(&self) -> Result { - if !IS_BUNDLING_SCRIPT_LOADED.lock().unwrap().is_loaded() { - if let Err(e) = loaders::from_memory("node", BUILD_SCRIPT) { - return Err(anyhow!("Cannot load bundling script: {e:?}")); - } - IS_BUNDLING_SCRIPT_LOADED.lock().unwrap().loaded(); - } - - if let Err(e) = metacall::( - BUNDLING_FUNC, - [ - serde_json::to_string(&self.targets)?, - self.dist_path.to_str().unwrap().to_owned(), - ], - ) { - return Err(anyhow!("Cannot running {BUNDLING_FUNC}(): {e:?}")); - } - - Ok(()) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use metacall::switch; - #[test] - fn it_works() { - let _metacall = switch::initialize().unwrap(); - WebBundler::new( - &HashMap::from([( - "pages/homes.tsx".to_owned(), - "../../tests/web-app/src/pages/home.tsx".to_owned(), - )]), - "../../tests/web-app/dist", - ) - .exec() - .unwrap() - } -} diff --git a/crates/metassr-build/src/client/mod.rs b/crates/metassr-build/src/client/mod.rs index 25deb49..6fcfbcf 100644 --- a/crates/metassr-build/src/client/mod.rs +++ b/crates/metassr-build/src/client/mod.rs @@ -1,10 +1,12 @@ -use crate::bundler::WebBundler; -use crate::traits::{Build, Exec, Generate}; +use crate::traits::{Build, Generate}; use crate::utils::setup_page_path; use anyhow::{anyhow, Result}; use hydrator::Hydrator; -use metassr_utils::src_analyzer::special_entries; -use metassr_utils::{cache_dir::CacheDir, src_analyzer::SourceDir, traits::AnalyzeDir}; + +use metassr_bundler::WebBundler; +use metassr_utils::{ + cache_dir::CacheDir, src_analyzer::special_entries, src_analyzer::SourceDir, traits::AnalyzeDir, +}; use std::{ collections::HashMap, ffi::OsStr, @@ -66,7 +68,7 @@ impl Build for ClientBuilder { (entry_name.to_owned(), format!("{}", fullpath.display())) }) .collect::>(); - + let bundler = WebBundler::new(&targets, &self.dist_path); if let Err(e) = bundler.exec() { return Err(anyhow!("Bundling failed: {e}")); diff --git a/crates/metassr-build/src/server/mod.rs b/crates/metassr-build/src/server/mod.rs index e8ecf00..a81c964 100644 --- a/crates/metassr-build/src/server/mod.rs +++ b/crates/metassr-build/src/server/mod.rs @@ -6,11 +6,10 @@ mod render; mod render_exec; mod targets; -use crate::{ - bundler::WebBundler, - traits::{Build, Exec}, -}; +use crate::traits::Build; use manifest::ManifestGenerator; + +use metassr_bundler::WebBundler; use metassr_utils::{ cache_dir::CacheDir, dist_analyzer::DistDir, diff --git a/crates/metassr-build/src/server/renderer/head.rs b/crates/metassr-build/src/server/renderer/head.rs index f009e53..5ecaa21 100644 --- a/crates/metassr-build/src/server/renderer/head.rs +++ b/crates/metassr-build/src/server/renderer/head.rs @@ -6,7 +6,7 @@ use std::{ collections::HashMap, ffi::OsStr, path::PathBuf, sync::Mutex, thread::sleep, time::Duration, }; -use crate::{bundler::WebBundler, traits::Exec}; +use metassr_bundler::WebBundler; lazy_static! { static ref IS_HEAD_SCRIPT_LOADED: Mutex = @@ -52,7 +52,8 @@ impl HeadRenderer { } pub fn render(&mut self, bundler: bool) -> Result { - if !IS_HEAD_SCRIPT_LOADED.lock().unwrap().is_loaded() { + let mut guard = IS_HEAD_SCRIPT_LOADED.lock().unwrap(); + if !guard.is_loaded() { if bundler { self.bundle()?; // TODO: remove this line @@ -63,8 +64,10 @@ impl HeadRenderer { "node", format!("{}/head.js", self.cache_dir.dir_path().display()), ); - IS_HEAD_SCRIPT_LOADED.lock().unwrap().loaded() + guard.loaded() } + drop(guard); + match metacall_no_arg::("render_head") { Err(e) => Err(anyhow!("Couldn't render head: {e:?}")), Ok(out) => Ok(out), diff --git a/crates/metassr-bundler/Cargo.toml b/crates/metassr-bundler/Cargo.toml new file mode 100644 index 0000000..1028b8f --- /dev/null +++ b/crates/metassr-bundler/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "metassr-bundler" +version = "0.0.1-alpha" +edition = "2021" +description = "A simple crate is used for web bundling built on Metacall and Rspack." +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +anyhow = "1.0.86" +lazy_static = "1.5.0" +metacall = "0.4.1" +metassr-utils = { version = "0.1.0", path = "../metassr-utils" } +serde_json = "1.0.128" diff --git a/crates/metassr-build/src/scripts/bundle.js b/crates/metassr-bundler/src/bundle.js similarity index 100% rename from crates/metassr-build/src/scripts/bundle.js rename to crates/metassr-bundler/src/bundle.js diff --git a/crates/metassr-bundler/src/lib.rs b/crates/metassr-bundler/src/lib.rs new file mode 100644 index 0000000..21a124f --- /dev/null +++ b/crates/metassr-bundler/src/lib.rs @@ -0,0 +1,98 @@ +use anyhow::{anyhow, Result}; +use lazy_static::lazy_static; +use metacall::{loaders, metacall, MetacallNull}; +use std::{collections::HashMap, ffi::OsStr, marker::Sized, path::Path, sync::Mutex}; + +lazy_static! { + static ref IS_BUNDLING_SCRIPT_LOADED: Mutex = + Mutex::new(BundleSciptLoadingState::new()); +} +static BUILD_SCRIPT: &str = include_str!("./bundle.js"); +const BUNDLING_FUNC: &str = "web_bundling"; + +/// A detector for if the bundling script `./bundle.js` is loaded or not. +#[derive(Debug)] +pub struct BundleSciptLoadingState(bool); + +impl BundleSciptLoadingState { + pub fn new() -> Self { + Self(false) + } + pub fn loaded(&mut self) { + self.0 = true + } + pub fn is_loaded(&self) -> bool { + self.0 + } +} + +impl Default for BundleSciptLoadingState { + fn default() -> Self { + Self::new() + } +} + +#[derive(Debug)] + +pub struct WebBundler<'a> { + pub targets: HashMap, + pub dist_path: &'a Path, +} + +impl<'a> WebBundler<'a> { + pub fn new(targets: &'a HashMap, dist_path: &'a S) -> Self + where + S: AsRef + ?Sized, + { + let targets: HashMap = targets + .iter() + .map(|(k, v)| (k.into(), Path::new(v))) + .collect(); + + Self { + targets, + dist_path: Path::new(dist_path), + } + } + pub fn exec(&self) -> Result<()> { + let mut guard = IS_BUNDLING_SCRIPT_LOADED.lock().unwrap(); + if !guard.is_loaded() { + if let Err(e) = loaders::from_memory("node", BUILD_SCRIPT) { + return Err(anyhow!("Cannot load bundling script: {e:?}")); + } + guard.loaded(); + } + drop(guard); + + if let Err(e) = metacall::( + BUNDLING_FUNC, + [ + serde_json::to_string(&self.targets)?, + self.dist_path.to_str().unwrap().to_owned(), + ], + ) { + return Err(anyhow!("Cannot running {BUNDLING_FUNC}(): {e:?}")); + } + + Ok(()) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use metacall::switch; + #[test] + fn it_works() { + let _metacall = switch::initialize().unwrap(); + WebBundler::new( + &HashMap::from([( + "pages/homes.tsx".to_owned(), + "../../tests/web-app/src/pages/home.tsx".to_owned(), + )]), + "../../tests/web-app/dist", + ) + .exec() + .unwrap() + } +}