mirror of
https://github.com/tauri-apps/tauri.git
synced 2026-04-03 10:11:15 +02:00
fix(cli): dev config reload (#1172)
* fix(cli): `dev` config reload * refactor: remove unnecessary mutex on config * fix: clippy * fix(cli/core): don't rebuild twice * fix(core/cli/dev): don't kill app twice Co-authored-by: Noah Klayman <noahklayman@gmail.com>
This commit is contained in:
committed by
GitHub
parent
5f3d31b367
commit
eeb46ad585
@@ -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(())
|
||||
|
||||
@@ -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<SharedChild>;
|
||||
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)
|
||||
|
||||
@@ -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<Config> = OnceCell::new();
|
||||
pub type ConfigHandle = Arc<Mutex<Option<Config>>>;
|
||||
|
||||
fn config_handle() -> &'static ConfigHandle {
|
||||
static CONFING_HANDLE: Lazy<ConfigHandle> = 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<ConfigHandle> {
|
||||
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<ConfigHandle> {
|
||||
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(())
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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
|
||||
})
|
||||
|
||||
@@ -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",
|
||||
|
||||
Reference in New Issue
Block a user