Pārlūkot izejas kodu

make backend and frontend builds happen in parallel

Evan Almloff 1 gadu atpakaļ
vecāks
revīzija
8b125231f0

+ 14 - 13
packages/cli/src/builder.rs

@@ -5,6 +5,7 @@ use crate::{
 };
 };
 use cargo_metadata::{diagnostic::Diagnostic, Message};
 use cargo_metadata::{diagnostic::Diagnostic, Message};
 use indicatif::{ProgressBar, ProgressStyle};
 use indicatif::{ProgressBar, ProgressStyle};
+use lazy_static::lazy_static;
 use manganis_cli_support::AssetManifestExt;
 use manganis_cli_support::AssetManifestExt;
 use serde::Serialize;
 use serde::Serialize;
 use std::{
 use std::{
@@ -16,6 +17,10 @@ use std::{
 };
 };
 use wasm_bindgen_cli_support::Bindgen;
 use wasm_bindgen_cli_support::Bindgen;
 
 
+lazy_static! {
+    static ref PROGRESS_BARS: indicatif::MultiProgress = indicatif::MultiProgress::new();
+}
+
 #[derive(Serialize, Debug, Clone)]
 #[derive(Serialize, Debug, Clone)]
 pub struct BuildResult {
 pub struct BuildResult {
     pub warnings: Vec<Diagnostic>,
     pub warnings: Vec<Diagnostic>,
@@ -25,7 +30,7 @@ pub struct BuildResult {
 pub fn build(config: &CrateConfig, _: bool, skip_assets: bool) -> Result<BuildResult> {
 pub fn build(config: &CrateConfig, _: bool, skip_assets: bool) -> Result<BuildResult> {
     // [1] Build the project with cargo, generating a wasm32-unknown-unknown target (is there a more specific, better target to leverage?)
     // [1] Build the project with cargo, generating a wasm32-unknown-unknown target (is there a more specific, better target to leverage?)
     // [2] Generate the appropriate build folders
     // [2] Generate the appropriate build folders
-    // [3] Wasm-bindgen the .wasm fiile, and move it into the {builddir}/modules/xxxx/xxxx_bg.wasm
+    // [3] Wasm-bindgen the .wasm file, and move it into the {builddir}/modules/xxxx/xxxx_bg.wasm
     // [4] Wasm-opt the .wasm file with whatever optimizations need to be done
     // [4] Wasm-opt the .wasm file with whatever optimizations need to be done
     // [5][OPTIONAL] Builds the Tailwind CSS file using the Tailwind standalone binary
     // [5][OPTIONAL] Builds the Tailwind CSS file using the Tailwind standalone binary
     // [6] Link up the html page to the wasm module
     // [6] Link up the html page to the wasm module
@@ -61,8 +66,8 @@ pub fn build(config: &CrateConfig, _: bool, skip_assets: bool) -> Result<BuildRe
             .output()?;
             .output()?;
     }
     }
 
 
-    let cmd = subprocess::Exec::cmd("cargo");
-    let cmd = cmd
+    let cmd = subprocess::Exec::cmd("cargo")
+        .env("CARGO_TARGET_DIR", target_dir)
         .cwd(crate_dir)
         .cwd(crate_dir)
         .arg("build")
         .arg("build")
         .arg("--target")
         .arg("--target")
@@ -272,6 +277,7 @@ pub fn build_desktop(
     let ignore_files = build_assets(config)?;
     let ignore_files = build_assets(config)?;
 
 
     let mut cmd = subprocess::Exec::cmd("cargo")
     let mut cmd = subprocess::Exec::cmd("cargo")
+        .env("CARGO_TARGET_DIR", &config.target_dir)
         .cwd(&config.crate_dir)
         .cwd(&config.crate_dir)
         .arg("build")
         .arg("build")
         .arg("--quiet")
         .arg("--quiet")
@@ -404,8 +410,9 @@ fn create_assets_head(config: &CrateConfig) -> Result<()> {
 fn prettier_build(cmd: subprocess::Exec) -> anyhow::Result<Vec<Diagnostic>> {
 fn prettier_build(cmd: subprocess::Exec) -> anyhow::Result<Vec<Diagnostic>> {
     let mut warning_messages: Vec<Diagnostic> = vec![];
     let mut warning_messages: Vec<Diagnostic> = vec![];
 
 
-    let pb = ProgressBar::new_spinner();
+    let mut pb = ProgressBar::new_spinner();
     pb.enable_steady_tick(Duration::from_millis(200));
     pb.enable_steady_tick(Duration::from_millis(200));
+    pb = PROGRESS_BARS.add(pb);
     pb.set_style(
     pb.set_style(
         ProgressStyle::with_template("{spinner:.dim.bold} {wide_msg}")
         ProgressStyle::with_template("{spinner:.dim.bold} {wide_msg}")
             .unwrap()
             .unwrap()
@@ -413,14 +420,6 @@ fn prettier_build(cmd: subprocess::Exec) -> anyhow::Result<Vec<Diagnostic>> {
     );
     );
     pb.set_message("💼 Waiting to start build the project...");
     pb.set_message("💼 Waiting to start build the project...");
 
 
-    struct StopSpinOnDrop(ProgressBar);
-
-    impl Drop for StopSpinOnDrop {
-        fn drop(&mut self) {
-            self.0.finish_and_clear();
-        }
-    }
-
     let stdout = cmd.detached().stream_stdout()?;
     let stdout = cmd.detached().stream_stdout()?;
     let reader = std::io::BufReader::new(stdout);
     let reader = std::io::BufReader::new(stdout);
 
 
@@ -456,7 +455,9 @@ fn prettier_build(cmd: subprocess::Exec) -> anyhow::Result<Vec<Diagnostic>> {
                     std::process::exit(1);
                     std::process::exit(1);
                 }
                 }
             }
             }
-            _ => (), // Unknown message
+            _ => {
+                // Unknown message
+            }
         }
         }
     }
     }
     Ok(warning_messages)
     Ok(warning_messages)

+ 4 - 1
packages/cli/src/cli/build.rs

@@ -15,8 +15,11 @@ pub struct Build {
 }
 }
 
 
 impl Build {
 impl Build {
-    pub fn build(self, bin: Option<PathBuf>) -> Result<()> {
+    pub fn build(self, bin: Option<PathBuf>, target_dir: Option<&std::path::Path>) -> Result<()> {
         let mut crate_config = crate::CrateConfig::new(bin)?;
         let mut crate_config = crate::CrateConfig::new(bin)?;
+        if let Some(target_dir) = target_dir {
+            crate_config.target_dir = target_dir.to_path_buf();
+        }
 
 
         // change the release state.
         // change the release state.
         crate_config.with_release(self.build.release);
         crate_config.with_release(self.build.release);

+ 1 - 1
packages/cli/src/cli/cfg.rs

@@ -112,7 +112,7 @@ pub struct ConfigOptsServe {
     #[clap(long)]
     #[clap(long)]
     pub profile: Option<String>,
     pub profile: Option<String>,
 
 
-    /// Build platform: support Web & Desktop [default: "default_platform"]
+    /// Build platform: support Web, Desktop, and Fullstack [default: "default_platform"]
     #[clap(long, value_enum)]
     #[clap(long, value_enum)]
     pub platform: Option<Platform>,
     pub platform: Option<Platform>,
 
 

+ 1 - 1
packages/cli/src/main.rs

@@ -61,7 +61,7 @@ async fn main() -> anyhow::Result<()> {
             .map_err(|e| anyhow!("🚫 Translation of HTML into RSX failed: {}", e)),
             .map_err(|e| anyhow!("🚫 Translation of HTML into RSX failed: {}", e)),
 
 
         Build(opts) => opts
         Build(opts) => opts
-            .build(Some(bin.clone()))
+            .build(Some(bin.clone()), None)
             .map_err(|e| anyhow!("🚫 Building project failed: {}", e)),
             .map_err(|e| anyhow!("🚫 Building project failed: {}", e)),
 
 
         Clean(opts) => opts
         Clean(opts) => opts

+ 23 - 8
packages/cli/src/server/fullstack/mod.rs

@@ -9,6 +9,16 @@ pub async fn startup(config: CrateConfig, serve: &ConfigOptsServe) -> Result<()>
     desktop::startup_with_platform::<FullstackPlatform>(config, serve).await
     desktop::startup_with_platform::<FullstackPlatform>(config, serve).await
 }
 }
 
 
+fn start_web_build_thread(
+    config: &CrateConfig,
+    serve: &ConfigOptsServe,
+) -> std::thread::JoinHandle<Result<()>> {
+    let serve = serve.clone();
+    let target_directory = config.crate_dir.join(".dioxus").join("web");
+    std::fs::create_dir_all(&target_directory).unwrap();
+    std::thread::spawn(move || build_web(serve, &target_directory))
+}
+
 struct FullstackPlatform {
 struct FullstackPlatform {
     serve: ConfigOptsServe,
     serve: ConfigOptsServe,
     desktop: desktop::DesktopPlatform,
     desktop: desktop::DesktopPlatform,
@@ -20,9 +30,7 @@ impl Platform for FullstackPlatform {
     where
     where
         Self: Sized,
         Self: Sized,
     {
     {
-        {
-            build_web(serve.clone())?;
-        }
+        let thread_handle = start_web_build_thread(config, serve);
 
 
         let mut desktop_config = config.clone();
         let mut desktop_config = config.clone();
         let desktop_feature = serve.server_feature.clone();
         let desktop_feature = serve.server_feature.clone();
@@ -35,6 +43,9 @@ impl Platform for FullstackPlatform {
         };
         };
         let config = WebAssetConfigDropGuard::new();
         let config = WebAssetConfigDropGuard::new();
         let desktop = desktop::DesktopPlatform::start(&desktop_config, serve)?;
         let desktop = desktop::DesktopPlatform::start(&desktop_config, serve)?;
+        thread_handle
+            .join()
+            .map_err(|_| anyhow::anyhow!("Failed to join thread"))??;
 
 
         Ok(Self {
         Ok(Self {
             desktop,
             desktop,
@@ -44,8 +55,8 @@ impl Platform for FullstackPlatform {
     }
     }
 
 
     fn rebuild(&mut self, crate_config: &CrateConfig) -> Result<crate::BuildResult> {
     fn rebuild(&mut self, crate_config: &CrateConfig) -> Result<crate::BuildResult> {
-        build_web(self.serve.clone())?;
-        {
+        let thread_handle = start_web_build_thread(crate_config, &self.serve);
+        let result = {
             let mut desktop_config = crate_config.clone();
             let mut desktop_config = crate_config.clone();
             let desktop_feature = self.serve.server_feature.clone();
             let desktop_feature = self.serve.server_feature.clone();
             let features = &mut desktop_config.features;
             let features = &mut desktop_config.features;
@@ -57,11 +68,15 @@ impl Platform for FullstackPlatform {
             };
             };
             let _gaurd = FullstackServerEnvGuard::new(self.serve.debug);
             let _gaurd = FullstackServerEnvGuard::new(self.serve.debug);
             self.desktop.rebuild(&desktop_config)
             self.desktop.rebuild(&desktop_config)
-        }
+        };
+        thread_handle
+            .join()
+            .map_err(|_| anyhow::anyhow!("Failed to join thread"))??;
+        result
     }
     }
 }
 }
 
 
-fn build_web(serve: ConfigOptsServe) -> Result<()> {
+fn build_web(serve: ConfigOptsServe, target_directory: &std::path::Path) -> Result<()> {
     let mut web_config: ConfigOptsBuild = serve.into();
     let mut web_config: ConfigOptsBuild = serve.into();
     let web_feature = web_config.client_feature.clone();
     let web_feature = web_config.client_feature.clone();
     let features = &mut web_config.features;
     let features = &mut web_config.features;
@@ -74,7 +89,7 @@ fn build_web(serve: ConfigOptsServe) -> Result<()> {
     web_config.platform = Some(crate::cfg::Platform::Web);
     web_config.platform = Some(crate::cfg::Platform::Web);
 
 
     let _gaurd = FullstackWebEnvGuard::new(web_config.debug);
     let _gaurd = FullstackWebEnvGuard::new(web_config.debug);
-    crate::cli::build::Build { build: web_config }.build(None)
+    crate::cli::build::Build { build: web_config }.build(None, Some(target_directory))
 }
 }
 
 
 // Debug mode web builds have a very large size by default. If debug mode is not enabled, we strip some of the debug info by default
 // Debug mode web builds have a very large size by default. If debug mode is not enabled, we strip some of the debug info by default

+ 2 - 1
packages/fullstack/examples/axum-auth/.gitignore

@@ -1,3 +1,4 @@
 dist
 dist
 target
 target
-static
+static
+.dioxus

+ 3 - 1
packages/fullstack/examples/axum-desktop/.gitignore

@@ -1,2 +1,4 @@
 dist
 dist
-target
+target
+static
+.dioxus

+ 2 - 1
packages/fullstack/examples/axum-hello-world/.gitignore

@@ -1,3 +1,4 @@
 dist
 dist
 target
 target
-static
+static
+.dioxus

+ 2 - 1
packages/fullstack/examples/axum-router/.gitignore

@@ -1,3 +1,4 @@
 dist
 dist
 target
 target
-static
+static
+.dioxus

+ 2 - 1
packages/fullstack/examples/salvo-hello-world/.gitignore

@@ -1,3 +1,4 @@
 dist
 dist
 target
 target
-static
+static
+.dioxus

+ 2 - 1
packages/fullstack/examples/static-hydrated/.gitignore

@@ -1,3 +1,4 @@
 docs
 docs
 target
 target
-static
+static
+.dioxus

+ 2 - 1
packages/fullstack/examples/warp-hello-world/.gitignore

@@ -1,3 +1,4 @@
 dist
 dist
 target
 target
-static
+static
+.dioxus