Ver Fonte

feat: commit code

YuKun Liu há 3 anos atrás
pai
commit
526a88cab1
5 ficheiros alterados com 190 adições e 75 exclusões
  1. 57 9
      Cargo.lock
  2. 2 2
      Cargo.toml
  3. 47 26
      src/builder.rs
  4. 15 21
      src/cli/serve/mod.rs
  5. 69 17
      src/server/mod.rs

+ 57 - 9
Cargo.lock

@@ -396,9 +396,9 @@ dependencies = [
 
 [[package]]
 name = "cargo_metadata"
-version = "0.14.2"
+version = "0.15.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4acbb09d9ee8e23699b9634375c72795d095bf268439da88562cf9b501f181fa"
+checksum = "3abb7553d5b9b8421c6de7cb02606ff15e0c6eea7d8eadd75ef013fd636bec36"
 dependencies = [
  "camino",
  "cargo-platform",
@@ -590,6 +590,21 @@ dependencies = [
  "cache-padded",
 ]
 
+[[package]]
+name = "console"
+version = "0.15.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a28b32d32ca44b70c3e4acd7db1babf555fa026e385fb95f18028f88848b3c31"
+dependencies = [
+ "encode_unicode",
+ "libc",
+ "once_cell",
+ "regex",
+ "terminal_size",
+ "unicode-width",
+ "winapi",
+]
+
 [[package]]
 name = "console_error_panic_hook"
 version = "0.1.7"
@@ -872,7 +887,7 @@ dependencies = [
  "headers",
  "html_parser",
  "hyper",
- "loading",
+ "indicatif",
  "log",
  "notify",
  "proc-macro2",
@@ -1101,6 +1116,12 @@ version = "1.0.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "453440c271cf5577fd2a40e4942540cb7d0d2f85e27c8d07dd0023c925a67541"
 
+[[package]]
+name = "encode_unicode"
+version = "0.3.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f"
+
 [[package]]
 name = "encoding_rs"
 version = "0.8.31"
@@ -1906,6 +1927,17 @@ dependencies = [
  "hashbrown",
 ]
 
+[[package]]
+name = "indicatif"
+version = "0.17.0-rc.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4017d0ce94b8e91e29d2c78ed891e57e5ec3dc4371820a9d96abab4af09eb8ad"
+dependencies = [
+ "console",
+ "number_prefix",
+ "unicode-width",
+]
+
 [[package]]
 name = "inotify"
 version = "0.9.6"
@@ -2145,12 +2177,6 @@ version = "0.5.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f"
 
-[[package]]
-name = "loading"
-version = "0.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "676420b03272176423578148eee61319e893422694f6d96a394841cb0901357f"
-
 [[package]]
 name = "lock_api"
 version = "0.4.7"
@@ -2469,6 +2495,12 @@ dependencies = [
  "libc",
 ]
 
+[[package]]
+name = "number_prefix"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3"
+
 [[package]]
 name = "objc"
 version = "0.2.7"
@@ -3525,6 +3557,16 @@ dependencies = [
  "winapi-util",
 ]
 
+[[package]]
+name = "terminal_size"
+version = "0.1.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "633c1a546cee861a1a6d0dc69ebeca693bf4296661ba7852b9d21d159e0506df"
+dependencies = [
+ "libc",
+ "winapi",
+]
+
 [[package]]
 name = "textwrap"
 version = "0.15.0"
@@ -3893,6 +3935,12 @@ version = "1.9.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "7e8820f5d777f6224dc4be3632222971ac30164d4a258d595640799554ebfd99"
 
+[[package]]
+name = "unicode-width"
+version = "0.1.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973"
+
 [[package]]
 name = "unicode-xid"
 version = "0.2.3"

+ 2 - 2
Cargo.toml

@@ -29,14 +29,14 @@ notify = { version = "5.0.0-pre.13", features = ["serde"] }
 html_parser = "0.6.2"
 binary-install = "0.0.2"
 convert_case = "0.5.0"
-cargo_metadata = "0.14.1"
+cargo_metadata = "0.15.0"
 tokio = { version = "1.16.1", features = ["full"] }
 atty = "0.2.14"
 regex = "1.5.4"
 chrono = "0.4.19"
 anyhow = "1.0.53"
 hyper = "0.14.17"
-loading = "0.3.0"
+indicatif = "0.17.0-rc.11"
 
 axum = { version = "0.5.1", features = ["ws", "headers"] }
 tower-http = { version = "0.2.2", features = ["fs", "trace"] }

+ 47 - 26
src/builder.rs

@@ -4,19 +4,26 @@ use crate::{
     tools::Tool,
     DioxusConfig,
 };
-use cargo_metadata::Message;
-use loading::Loading;
+use cargo_metadata::{diagnostic::Diagnostic, Message};
+use indicatif::{ProgressBar, ProgressStyle};
+use serde::Serialize;
 use std::{
-    collections::HashMap,
     fs::{copy, create_dir_all, remove_dir_all, File},
     io::Read,
     panic,
     path::PathBuf,
     process::Command,
+    time::Duration,
 };
 use wasm_bindgen_cli_support::Bindgen;
 
-pub fn build(config: &CrateConfig, quiet: bool) -> Result<()> {
+#[derive(Serialize, Debug, Clone)]
+pub struct BuildResult {
+    pub warnings: Vec<Diagnostic>,
+    pub elapsed_time: u128,
+}
+
+pub fn build(config: &CrateConfig, quiet: bool) -> Result<BuildResult> {
     // [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
     // [3] Wasm-bindgen the .wasm fiile, and move it into the {builddir}/modules/xxxx/xxxx_bg.wasm
@@ -78,13 +85,7 @@ pub fn build(config: &CrateConfig, quiet: bool) -> Result<()> {
         ExecutableType::Example(name) => cmd.arg("--example").arg(name),
     };
 
-    prettier_build(cmd).unwrap();
-
-    // if !output.status.success() {
-    //     log::error!("Build failed!");
-    //     let reason = String::from_utf8_lossy(&output.stderr).to_string();
-    //     return Err(Error::BuildFailed(reason));
-    // }
+    let warning_messages = prettier_build(cmd)?;
 
     // [2] Establish the output directory structure
     let bindgen_outdir = out_dir.join("assets").join("dioxus");
@@ -122,8 +123,7 @@ pub fn build(config: &CrateConfig, quiet: bool) -> Result<()> {
             .unwrap();
     });
     if bindgen_result.is_err() {
-        log::error!("Bindgen build failed! \nThis is probably due to the Bindgen version, dioxus-cli using `0.2.79` Bindgen crate.");
-        return Ok(());
+        return Err(Error::BuildFailed("Bindgen build failed! \nThis is probably due to the Bindgen version, dioxus-cli using `0.2.79` Bindgen crate.".to_string()));
     }
 
     // check binaryen:wasm-opt tool
@@ -193,8 +193,10 @@ pub fn build(config: &CrateConfig, quiet: bool) -> Result<()> {
     }
 
     let t_end = std::time::Instant::now();
-    log::info!("🏁 Done in {}ms!", (t_end - t_start).as_millis());
-    Ok(())
+    Ok(BuildResult {
+        warnings: warning_messages,
+        elapsed_time: (t_end - t_start).as_millis()
+    })
 }
 
 pub fn build_desktop(config: &CrateConfig, is_serve: bool) -> Result<()> {
@@ -327,27 +329,46 @@ pub fn build_desktop(config: &CrateConfig, is_serve: bool) -> Result<()> {
     Ok(())
 }
 
-fn prettier_build(mut cmd: Command) -> anyhow::Result<()> {
-    let loading = Loading::default();
-    let mut record: HashMap<String, String> = HashMap::new();
+fn prettier_build(mut cmd: Command) -> anyhow::Result<Vec<Diagnostic>> {
+    let mut warning_messages: Vec<Diagnostic> = vec![];
+
+    let pb = ProgressBar::new_spinner();
+    pb.enable_steady_tick(Duration::from_millis(200));
+    pb.set_style(
+        ProgressStyle::with_template("{spinner:.dim.bold} {wide_msg}")
+            .unwrap()
+            .tick_chars("/|\\- "),
+    );
+    pb.set_message("Start to build project");
+
     let mut command = cmd.spawn()?;
     let reader = std::io::BufReader::new(command.stdout.take().unwrap());
     for message in cargo_metadata::Message::parse_stream(reader) {
         match message.unwrap() {
-            Message::CompilerMessage(_msg) => {
-                // println!("{:#?}", msg);
+            Message::CompilerMessage(msg) => {
+                let message = msg.message;
+                match message.level {
+                    cargo_metadata::diagnostic::DiagnosticLevel::Error => {
+                        log::error!("Build Failed: {}", message.message);
+                        std::process::exit(1);
+                    }
+                    cargo_metadata::diagnostic::DiagnosticLevel::Warning => {
+                        warning_messages.push(message.clone());
+                    }
+                    _ => {}
+                }
             }
             Message::CompilerArtifact(artifact) => {
-                record.insert(artifact.package_id.to_string(), artifact.target.name);
+                pb.set_message(format!("Compiling {} ", artifact.package_id));
+                pb.tick();
             }
             Message::BuildScriptExecuted(script) => {
-                let package_id = script.package_id.to_string();
-                if let Some(name) = record.get(&package_id) {
-                    loading.text(format!("[{}] build done", name));
-                }
+                let _package_id = script.package_id.to_string();
             }
             Message::BuildFinished(finished) => {
                 if finished.success {
+                    pb.finish_and_clear();
+                    println!("Done in");
                 } else {
                     std::process::exit(1);
                 }
@@ -355,7 +376,7 @@ fn prettier_build(mut cmd: Command) -> anyhow::Result<()> {
             _ => (), // Unknown message
         }
     }
-    Ok(())
+    Ok(warning_messages)
 }
 
 pub fn gen_page(config: &DioxusConfig, serve: bool) -> String {

+ 15 - 21
src/cli/serve/mod.rs

@@ -38,31 +38,25 @@ impl Serve {
                 .clone()
         });
 
-        match platform.as_str() {
-            "web" => {
-                crate::builder::build(&crate_config, false)?;
-            }
-            "desktop" => {
-                crate::builder::build_desktop(&crate_config, true)?;
+        if platform.as_str() == "desktop" {
+            crate::builder::build_desktop(&crate_config, true)?;
 
-                match &crate_config.executable {
-                    crate::ExecutableType::Binary(name)
-                    | crate::ExecutableType::Lib(name)
-                    | crate::ExecutableType::Example(name) => {
-                        let mut file = crate_config.out_dir.join(name);
-                        if cfg!(windows) {
-                            file.set_extension("exe");
-                        }
-                        Command::new(crate_config.out_dir.join(file).to_str().unwrap())
-                            .stdout(Stdio::inherit())
-                            .output()?;
+            match &crate_config.executable {
+                crate::ExecutableType::Binary(name)
+                | crate::ExecutableType::Lib(name)
+                | crate::ExecutableType::Example(name) => {
+                    let mut file = crate_config.out_dir.join(name);
+                    if cfg!(windows) {
+                        file.set_extension("exe");
                     }
+                    Command::new(crate_config.out_dir.join(file).to_str().unwrap())
+                        .stdout(Stdio::inherit())
+                        .output()?;
                 }
-                return Ok(());
-            }
-            _ => {
-                return custom_error!("Unsoppurt platform target.");
             }
+            return Ok(());
+        } else if platform != "web" {
+            return custom_error!("Unsoppurt platform target.");
         }
 
         // generate dev-index page

+ 69 - 17
src/server/mod.rs

@@ -6,6 +6,7 @@ use axum::{
     routing::{get, get_service},
     Router,
 };
+use cargo_metadata::diagnostic::Diagnostic;
 use colored::Colorize;
 use dioxus::rsx_interpreter::SetRsxMessage;
 use notify::{RecommendedWatcher, Watcher};
@@ -15,7 +16,7 @@ use std::{net::UdpSocket, path::PathBuf, process::Command, sync::Arc};
 use tower::ServiceBuilder;
 use tower_http::services::fs::{ServeDir, ServeFileSystemResponseBody};
 
-use crate::{builder, serve::Serve, CrateConfig, Result};
+use crate::{builder, serve::Serve, BuildResult, CrateConfig, Result};
 use tokio::sync::broadcast;
 
 mod hot_reload;
@@ -27,9 +28,9 @@ pub struct BuildManager {
 }
 
 impl BuildManager {
-    fn rebuild(&self) -> Result<()> {
+    fn rebuild(&self) -> Result<BuildResult> {
         log::info!("🪁 Rebuild project");
-        builder::build(&self.config, true)?;
+        let result = builder::build(&self.config, true)?;
         // change the websocket reload state to true;
         // the page will auto-reload.
         if self
@@ -43,7 +44,7 @@ impl BuildManager {
             let _ = Serve::regen_dev_page(&self.config);
         }
         let _ = self.reload_tx.send(());
-        Ok(())
+        Ok(result)
     }
 }
 
@@ -61,6 +62,8 @@ pub async fn startup(port: u16, config: CrateConfig) -> Result<()> {
 }
 
 pub async fn startup_hot_reload(port: u16, config: CrateConfig) -> Result<()> {
+    let first_build_result = crate::builder::build(&config, false)?;
+
     log::info!("🚀 Starting development server...");
 
     let dist_path = config.out_dir.clone();
@@ -159,9 +162,22 @@ pub async fn startup_hot_reload(port: u16, config: CrateConfig) -> Result<()> {
                     }
                 }
                 if needs_rebuild {
-                    print_console_info(port, &config, evt.paths);
-                    if let Err(err) = build_manager.rebuild() {
-                        log::error!("{}", err);
+                    match build_manager.rebuild() {
+                        Ok(res) => {
+                            print_console_info(
+                                port,
+                                &config,
+                                PrettierOptions {
+                                    changed: evt.paths,
+                                    warnings: res.warnings,
+                                    elapsed_time: res.elapsed_time,
+                                },
+                            );
+                        }
+                        Err(err) => {
+                            log::error!("{}", err);
+                            std::process::exit(1);
+                        }
                     }
                 }
                 if !messages.is_empty() {
@@ -183,7 +199,15 @@ pub async fn startup_hot_reload(port: u16, config: CrateConfig) -> Result<()> {
     }
 
     // start serve dev-server at 0.0.0.0:8080
-    print_console_info(port, &config, vec![]);
+    print_console_info(
+        port,
+        &config,
+        PrettierOptions {
+            changed: vec![],
+            warnings: first_build_result.warnings,
+            elapsed_time: first_build_result.elapsed_time,
+        },
+    );
 
     let file_service_config = config.clone();
     let file_service = ServiceBuilder::new()
@@ -246,6 +270,8 @@ pub async fn startup_hot_reload(port: u16, config: CrateConfig) -> Result<()> {
 }
 
 pub async fn startup_default(port: u16, config: CrateConfig) -> Result<()> {
+    let first_build_result = crate::builder::build(&config, false)?;
+
     log::info!("🚀 Starting development server...");
 
     let dist_path = config.out_dir.clone();
@@ -276,10 +302,20 @@ pub async fn startup_default(port: u16, config: CrateConfig) -> Result<()> {
     let mut watcher = RecommendedWatcher::new(move |info: notify::Result<notify::Event>| {
         let config = watcher_config.clone();
         if info.is_ok() {
-            print_console_info(port, &config, info.unwrap().paths);
             if chrono::Local::now().timestamp() > last_update_time {
                 match build_manager.rebuild() {
-                    Ok(_) => last_update_time = chrono::Local::now().timestamp(),
+                    Ok(res) => {
+                        last_update_time = chrono::Local::now().timestamp();
+                        print_console_info(
+                            port,
+                            &config,
+                            PrettierOptions {
+                                changed: info.unwrap().paths,
+                                warnings: res.warnings,
+                                elapsed_time: res.elapsed_time,
+                            },
+                        );
+                    }
                     Err(e) => log::error!("{}", e),
                 }
             }
@@ -297,8 +333,16 @@ pub async fn startup_default(port: u16, config: CrateConfig) -> Result<()> {
     }
 
     // start serve dev-server at 0.0.0.0
-    print_console_info(port, &config, vec![]);
-
+    print_console_info(
+        port,
+        &config,
+        PrettierOptions {
+            changed: vec![],
+            warnings: first_build_result.warnings,
+            elapsed_time: first_build_result.elapsed_time,
+        },
+    );
+    
     let file_service_config = config.clone();
     let file_service = ServiceBuilder::new()
         .and_then(
@@ -355,7 +399,14 @@ pub async fn startup_default(port: u16, config: CrateConfig) -> Result<()> {
     Ok(())
 }
 
-fn print_console_info(port: u16, config: &CrateConfig, changed: Vec<PathBuf>) {
+#[derive(Debug, Default)]
+pub struct PrettierOptions {
+    changed: Vec<PathBuf>,
+    warnings: Vec<Diagnostic>,
+    elapsed_time: u128,
+}
+
+fn print_console_info(port: u16, config: &CrateConfig, options: PrettierOptions) {
     print!(
         "{}",
         String::from_utf8_lossy(
@@ -413,7 +464,7 @@ fn print_console_info(port: u16, config: &CrateConfig, changed: Vec<PathBuf>) {
         "False"
     };
 
-    if changed.len() <= 0 {
+    if options.changed.len() <= 0 {
         println!(
             "{} @ v{}\n",
             "Dioxus".bold().green(),
@@ -422,7 +473,9 @@ fn print_console_info(port: u16, config: &CrateConfig, changed: Vec<PathBuf>) {
     } else {
         println!(
             "Project Reloaded: {}\n",
-            format!("Changed {} files.", changed.len()).purple().bold()
+            format!("Changed {} files.", options.changed.len())
+                .purple()
+                .bold()
         );
     }
     println!(
@@ -446,12 +499,11 @@ fn print_console_info(port: u16, config: &CrateConfig, changed: Vec<PathBuf>) {
     println!("\t> URL Rewrite [index_on_404] : {}", url_rewrite.purple());
     println!("");
 
-    if changed.len() <= 0 {
+    if options.changed.len() <= 0 {
         log::info!("{}", "Server startup completed.".green().bold());
     } else {
         log::info!("{}", "Project rebuild completed.".green().bold());
     }
-    
 }
 
 fn get_ip() -> Option<String> {