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:
Lucas Fernandes Nogueira
2021-02-01 21:32:15 -03:00
committed by GitHub
parent 5f3d31b367
commit eeb46ad585
6 changed files with 104 additions and 65 deletions

View File

@@ -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(())

View File

@@ -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)

View File

@@ -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(())
}

View File

@@ -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();

View File

@@ -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
})

View File

@@ -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",