diff --git a/cli/core/src/build.rs b/cli/core/src/build.rs index 854e4e184..9c909798f 100644 --- a/cli/core/src/build.rs +++ b/cli/core/src/build.rs @@ -52,7 +52,10 @@ impl Build { pub fn run(self) -> crate::Result<()> { let config = get_config(self.config.as_deref())?; - let feature = if config.tauri.embedded_server.active { + let config_guard = config.lock().unwrap(); + let config_ = config_guard.as_ref().unwrap(); + + let feature = if config_.tauri.embedded_server.active { "embedded-server" } else { "no-server" @@ -86,22 +89,26 @@ impl Build { let tauri_path = tauri_dir(); set_current_dir(&tauri_path)?; set_var("TAURI_DIR", &tauri_path); - set_var("TAURI_DIST_DIR", tauri_path.join(&config.build.dist_dir)); + set_var("TAURI_DIST_DIR", tauri_path.join(&config_.build.dist_dir)); - rewrite_manifest(&config)?; + drop(config_guard); + rewrite_manifest(config.clone())?; - let index_html_path = PathBuf::from(&config.build.dist_dir).join("index.html"); - let tauri_html = TauriHtml::new(&config.build.dist_dir, read_to_string(index_html_path)?) - .inliner_enabled(config.tauri.inliner.active && !config.tauri.embedded_server.active) - .global_tauri(config.build.with_global_tauri) + let config_guard = config.lock().unwrap(); + let config_ = config_guard.as_ref().unwrap(); + + let index_html_path = PathBuf::from(&config_.build.dist_dir).join("index.html"); + let tauri_html = TauriHtml::new(&config_.build.dist_dir, read_to_string(index_html_path)?) + .inliner_enabled(config_.tauri.inliner.active && !config_.tauri.embedded_server.active) + .global_tauri(config_.build.with_global_tauri) .generate()?; - let tauri_index_html_path = PathBuf::from(&config.build.dist_dir).join("index.tauri.html"); + let tauri_index_html_path = PathBuf::from(&config_.build.dist_dir).join("index.tauri.html"); let mut tauri_index_html_file = File::create(tauri_index_html_path)?; tauri_index_html_file.write_all(tauri_html.as_bytes())?; let settings = settings_builder.build()?; - if let Some(before_build) = &config.build.before_build_command { + if let Some(before_build) = &config_.build.before_build_command { let mut cmd: Option<&str> = None; let mut args: Vec<&str> = vec![]; for token in before_build.split(' ') { @@ -120,7 +127,7 @@ impl Build { } build_project(&settings)?; - if config.tauri.bundle.active { + if config_.tauri.bundle.active { bundle_project(settings)?; } Ok(()) diff --git a/cli/core/src/dev.rs b/cli/core/src/dev.rs index b2e5c52a1..1135323ad 100644 --- a/cli/core/src/dev.rs +++ b/cli/core/src/dev.rs @@ -1,6 +1,6 @@ use crate::helpers::{ app_paths::{app_dir, tauri_dir}, - config::{get as get_config, reload as reload_config, Config}, + config::{get as get_config, reload as reload_config, ConfigHandle}, manifest::rewrite_manifest, Logger, TauriHtml, }; @@ -52,13 +52,19 @@ impl Dev { pub fn run(self) -> crate::Result<()> { let logger = Logger::new("tauri:dev"); let tauri_path = tauri_dir(); - let config = get_config(self.config.as_deref())?; - let mut config_mut = config.clone(); + let merge_config = self.config.clone(); + let config = get_config(merge_config.as_deref())?; let mut _guard = None; let mut process: Arc; - let new_dev_path: String; - if let Some(before_dev) = &config.build.before_dev_command { + if let Some(before_dev) = &config + .lock() + .unwrap() + .as_ref() + .unwrap() + .build + .before_dev_command + { let mut cmd: Option<&str> = None; let mut args: Vec<&str> = vec![]; for token in before_dev.split(' ') { @@ -77,10 +83,17 @@ impl Dev { } } - let running_dev_server = config.build.dev_path.starts_with("http"); + let running_dev_server = config + .lock() + .unwrap() + .as_ref() + .unwrap() + .build + .dev_path + .starts_with("http"); - if running_dev_server { - let dev_path = Url::parse(&config.build.dev_path)?; + let new_dev_path = if running_dev_server { + let dev_path = Url::parse(&config.lock().unwrap().as_ref().unwrap().build.dev_path)?; let dev_port = dev_path.port().unwrap_or(80); let timeout = Duration::from_secs(3); @@ -105,27 +118,33 @@ impl Dev { logger.log(format!("starting dev proxy on port {}", proxy_port)); let config_ = config.clone(); - std::thread::spawn(move || proxy_dev_server(&config_, &proxy_path, proxy_port)); + std::thread::spawn(move || proxy_dev_server(config_, &proxy_path, proxy_port)); - new_dev_path = format!( + format!( "http://{}:{}", dev_path.host_str().expect("failed to read dev_path host"), proxy_port - ); + ) } else { - new_dev_path = tauri_dir() - .join(&config.build.dev_path) + tauri_dir() + .join(&config.lock().unwrap().as_ref().unwrap().build.dev_path) .to_string_lossy() - .to_string(); - } + .to_string() + }; - config_mut.build.dev_path = new_dev_path.clone(); + (*config.lock().unwrap()).as_mut().unwrap().build.dev_path = new_dev_path.to_string(); set_var("TAURI_DIR", &tauri_path); - set_var("TAURI_DIST_DIR", tauri_path.join(&config.build.dist_dir)); - set_var("TAURI_CONFIG", serde_json::to_string(&config_mut)?); + set_var( + "TAURI_DIST_DIR", + tauri_path.join(&config.lock().unwrap().as_ref().unwrap().build.dist_dir), + ); + set_var( + "TAURI_CONFIG", + serde_json::to_string(&*config.lock().unwrap())?, + ); - rewrite_manifest(&config)?; + rewrite_manifest(config.clone())?; let (child_wait_tx, child_wait_rx) = channel(); let child_wait_rx = Arc::new(Mutex::new(child_wait_rx)); @@ -134,13 +153,20 @@ impl Dev { let (tx, rx) = channel(); - let mut watcher = watcher(tx, Duration::from_secs(2)).unwrap(); + let mut watcher = watcher(tx, Duration::from_secs(1)).unwrap(); watcher.watch(tauri_path.join("src"), RecursiveMode::Recursive)?; watcher.watch(tauri_path.join("Cargo.toml"), RecursiveMode::Recursive)?; watcher.watch(tauri_path.join("tauri.conf.json"), RecursiveMode::Recursive)?; if !running_dev_server { watcher.watch( - config_mut.build.dev_path.to_string(), + config + .lock() + .unwrap() + .as_ref() + .unwrap() + .build + .dev_path + .to_string(), RecursiveMode::Recursive, )?; } @@ -156,16 +182,19 @@ impl Dev { }; if let Some(event_path) = event_path { - let _ = child_wait_tx.send(true); - process.kill()?; if event_path.file_name() == Some(OsStr::new("tauri.conf.json")) { - config_mut = reload_config(Some(&serde_json::to_string(&config_mut)?))?.clone(); - rewrite_manifest(&config_mut)?; - config_mut.build.dev_path = new_dev_path.clone(); - set_var("TAURI_CONFIG", serde_json::to_string(&config_mut)?); + reload_config(merge_config.as_deref())?; + (*config.lock().unwrap()).as_mut().unwrap().build.dev_path = new_dev_path.to_string(); + rewrite_manifest(config.clone())?; + set_var("TAURI_CONFIG", serde_json::to_string(&*config)?); + } else { + // When tauri.conf.json is changed, rewrite_manifest will be called + // which will trigger the watcher again + // So the app should only be started when a file other than tauri.conf.json is changed + let _ = child_wait_tx.send(true); + process.kill()?; + process = self.start_app(child_wait_rx.clone()); } - - process = self.start_app(child_wait_rx.clone()); } } } @@ -196,7 +225,7 @@ impl Dev { } } -fn proxy_dev_server(config: &Config, dev_path: &Url, dev_port: u16) -> crate::Result<()> { +fn proxy_dev_server(config: ConfigHandle, dev_path: &Url, dev_port: u16) -> crate::Result<()> { let server_url = format!( "{}:{}", dev_path.host_str().expect("failed to read dev_path host"), @@ -218,6 +247,8 @@ fn proxy_dev_server(config: &Config, dev_path: &Url, dev_port: u16) -> crate::Re } if request_url == "/" { + let config_guard = config.lock().unwrap(); + let config = config_guard.as_ref().unwrap(); let response = request_builder.send()?.text()?; let tauri_html = TauriHtml::new(&config.build.dist_dir, response) .global_tauri(config.build.with_global_tauri) diff --git a/cli/core/src/helpers/config.rs b/cli/core/src/helpers/config.rs index 98c63c9a3..6ee0515b1 100644 --- a/cli/core/src/helpers/config.rs +++ b/cli/core/src/helpers/config.rs @@ -1,5 +1,5 @@ use json_patch::merge; -use once_cell::sync::OnceCell; +use once_cell::sync::Lazy; use serde::de::{Deserializer, Error as DeError, Visitor}; use serde::ser::Serializer; use serde::{Deserialize, Serialize}; @@ -8,8 +8,14 @@ use serde_json::Value as JsonValue; use std::collections::HashMap; use std::fs::File; use std::io::BufReader; +use std::sync::{Arc, Mutex}; -static CONFIG: OnceCell = OnceCell::new(); +pub type ConfigHandle = Arc>>; + +fn config_handle() -> &'static ConfigHandle { + static CONFING_HANDLE: Lazy = Lazy::new(Default::default); + &CONFING_HANDLE +} /// The window configuration object. #[derive(PartialEq, Clone, Deserialize, Serialize, Debug)] @@ -390,11 +396,9 @@ fn default_build() -> BuildConfig { } /// Gets the static parsed config from `tauri.conf.json`. -fn get_internal(merge_config: Option<&str>, reload: bool) -> crate::Result<&'static Config> { - if let Some(config) = CONFIG.get() { - if !reload { - return Ok(config); - } +fn get_internal(merge_config: Option<&str>, reload: bool) -> crate::Result { + if !reload && config_handle().lock().unwrap().is_some() { + return Ok(config_handle().clone()); } let path = super::app_paths::tauri_dir().join("tauri.conf.json"); @@ -408,19 +412,16 @@ fn get_internal(merge_config: Option<&str>, reload: bool) -> crate::Result<&'sta } let config = serde_json::from_value(config)?; + *config_handle().lock().unwrap() = Some(config); - CONFIG - .set(config) - .map_err(|_| anyhow::anyhow!("failed to set CONFIG"))?; - - let config = CONFIG.get().unwrap(); - Ok(config) + Ok(config_handle().clone()) } -pub fn get(merge_config: Option<&str>) -> crate::Result<&'static Config> { +pub fn get(merge_config: Option<&str>) -> crate::Result { get_internal(merge_config, false) } -pub fn reload(merge_config: Option<&str>) -> crate::Result<&'static Config> { - get_internal(merge_config, true) +pub fn reload(merge_config: Option<&str>) -> crate::Result<()> { + get_internal(merge_config, true)?; + Ok(()) } diff --git a/cli/core/src/helpers/manifest.rs b/cli/core/src/helpers/manifest.rs index 9e129f763..6da725185 100644 --- a/cli/core/src/helpers/manifest.rs +++ b/cli/core/src/helpers/manifest.rs @@ -1,4 +1,4 @@ -use super::{app_paths::tauri_dir, config::Config}; +use super::{app_paths::tauri_dir, config::ConfigHandle}; use convert_case::{Case, Casing}; use toml_edit::{Array, Document, Value}; @@ -6,7 +6,7 @@ use toml_edit::{Array, Document, Value}; use std::fs::File; use std::io::{Read, Write}; -pub fn rewrite_manifest(config: &Config) -> crate::Result<()> { +pub fn rewrite_manifest(config: ConfigHandle) -> crate::Result<()> { let manifest_path = tauri_dir().join("Cargo.toml"); let mut manifest_str = String::new(); let mut manifest_file = File::open(&manifest_path)?; @@ -20,6 +20,10 @@ pub fn rewrite_manifest(config: &Config) -> crate::Result<()> { let entry = dependencies.entry("tauri"); let tauri = entry.as_value_mut(); + + let config_guard = config.lock().unwrap(); + let config = config_guard.as_ref().unwrap(); + if let Some(tauri) = tauri { let mut features: Array = Default::default(); diff --git a/tauri/examples/communication/dist/index.tauri.html b/tauri/examples/communication/dist/index.tauri.html index ae01838b3..c0bb3dcd4 100644 --- a/tauri/examples/communication/dist/index.tauri.html +++ b/tauri/examples/communication/dist/index.tauri.html @@ -142,11 +142,7 @@ if (!String.prototype.startsWith) { function (e) { var target = e.target while (target != null) { - if ( - target.matches - ? target.matches('img') - : target.msMatchesSelector('img') - ) { + if (target.matches('img')) { window.__TAURI__.loadAsset(target.src, 'image').then(function (img) { target.src = img }) diff --git a/tauri/examples/communication/src-tauri/Cargo.lock b/tauri/examples/communication/src-tauri/Cargo.lock index 7397a8372..7f8d93dc8 100644 --- a/tauri/examples/communication/src-tauri/Cargo.lock +++ b/tauri/examples/communication/src-tauri/Cargo.lock @@ -1509,9 +1509,9 @@ dependencies = [ [[package]] name = "tiny_http" -version = "0.7.0" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15ce4fc3c4cdea1a4399bb1819a539195fb69db4bbe0bde5b7c7f18fed412e02" +checksum = "eded47106b8e52d8ed8119f0ea6e8c0f5881e69783e0297b5a8462958f334bc1" dependencies = [ "ascii", "chrono",