Use Manganis Linker System (#2561)
* feat: new manganis linker * revision: fmt, clippy, cleanup * revision: link subcommand * fix: async runtime * revision: remove working dir arg * revision: switch dep source * fix: matrix, playwright * fix: fullstack manganis
This commit is contained in:
1 parent
90c46afd12
commit
2ef406982e
15 files changed
+330
-170
No files matched your search
@@ -1,4 +1,5 @@
|
||||
use brotli::enc::BrotliEncoderParams;
|
||||
use std::fs;
|
||||
use std::path::Path;
|
||||
use std::{ffi::OsString, path::PathBuf};
|
||||
use walkdir::WalkDir;
|
||||
@@ -10,12 +11,16 @@ use dioxus_cli_config::CrateConfig;
|
||||
use dioxus_cli_config::Platform;
|
||||
use manganis_cli_support::{AssetManifest, AssetManifestExt};
|
||||
|
||||
pub fn asset_manifest(bin: Option<&str>, crate_config: &CrateConfig) -> AssetManifest {
|
||||
AssetManifest::load_from_path(
|
||||
bin,
|
||||
crate_config.crate_dir.join("Cargo.toml"),
|
||||
crate_config.workspace_dir.join("Cargo.lock"),
|
||||
)
|
||||
/// The temp file name for passing manganis json from linker to current exec.
|
||||
pub const MG_JSON_OUT: &str = "mg-out";
|
||||
|
||||
pub fn asset_manifest(config: &CrateConfig) -> AssetManifest {
|
||||
let file_path = config.out_dir().join(MG_JSON_OUT);
|
||||
let read = fs::read_to_string(&file_path).unwrap();
|
||||
_ = fs::remove_file(file_path);
|
||||
let json: Vec<String> = serde_json::from_str(&read).unwrap();
|
||||
|
||||
AssetManifest::load(json)
|
||||
}
|
||||
|
||||
/// Create a head file that contains all of the imports for assets that the user project uses
|
||||
|
||||
+89
-43
@@ -4,6 +4,7 @@ use crate::{
|
||||
AssetConfigDropGuard,
|
||||
},
|
||||
error::{Error, Result},
|
||||
link::LinkCommand,
|
||||
tools::Tool,
|
||||
};
|
||||
use anyhow::Context;
|
||||
@@ -83,13 +84,12 @@ pub fn build_web(
|
||||
let CrateConfig {
|
||||
crate_dir,
|
||||
target_dir,
|
||||
executable,
|
||||
dioxus_config,
|
||||
..
|
||||
} = config;
|
||||
let out_dir = config.out_dir();
|
||||
|
||||
let _guard = AssetConfigDropGuard::new();
|
||||
let _asset_guard = AssetConfigDropGuard::new();
|
||||
let _manganis_support = ManganisSupportGuard::default();
|
||||
|
||||
// start to build the assets
|
||||
@@ -114,54 +114,76 @@ pub fn build_web(
|
||||
}
|
||||
}
|
||||
|
||||
let cmd = subprocess::Exec::cmd("cargo")
|
||||
let mut cargo_args = vec!["--target".to_string(), "wasm32-unknown-unknown".to_string()];
|
||||
|
||||
let mut cmd = subprocess::Exec::cmd("cargo")
|
||||
.set_rust_flags(rust_flags)
|
||||
.env("CARGO_TARGET_DIR", target_dir)
|
||||
.cwd(crate_dir)
|
||||
.arg("build")
|
||||
.arg("--target")
|
||||
.arg("wasm32-unknown-unknown")
|
||||
.arg("--message-format=json-render-diagnostics");
|
||||
|
||||
// TODO: make the initial variable mutable to simplify all the expressions
|
||||
// below. Look inside the `build_desktop()` as an example.
|
||||
let cmd = if config.release {
|
||||
cmd.arg("--release")
|
||||
if config.release {
|
||||
cargo_args.push("--release".to_string());
|
||||
}
|
||||
if config.verbose {
|
||||
cargo_args.push("--verbose".to_string());
|
||||
} else {
|
||||
cmd
|
||||
};
|
||||
let cmd = if config.verbose {
|
||||
cmd.arg("--verbose")
|
||||
} else {
|
||||
cmd.arg("--quiet")
|
||||
};
|
||||
cargo_args.push("--quiet".to_string());
|
||||
}
|
||||
|
||||
let cmd = if config.custom_profile.is_some() {
|
||||
if config.custom_profile.is_some() {
|
||||
let custom_profile = config.custom_profile.as_ref().unwrap();
|
||||
cmd.arg("--profile").arg(custom_profile)
|
||||
} else {
|
||||
cmd
|
||||
};
|
||||
cargo_args.push("--profile".to_string());
|
||||
cargo_args.push(custom_profile.to_string());
|
||||
}
|
||||
|
||||
let cmd = if config.features.is_some() {
|
||||
if config.features.is_some() {
|
||||
let features_str = config.features.as_ref().unwrap().join(" ");
|
||||
cmd.arg("--features").arg(features_str)
|
||||
} else {
|
||||
cmd
|
||||
};
|
||||
cargo_args.push("--features".to_string());
|
||||
cargo_args.push(features_str);
|
||||
}
|
||||
|
||||
let cmd = cmd.args(&config.cargo_args);
|
||||
if let Some(target) = &config.target {
|
||||
cargo_args.push("--target".to_string());
|
||||
cargo_args.push(target.clone());
|
||||
}
|
||||
|
||||
let cmd = match executable {
|
||||
ExecutableType::Binary(name) => cmd.arg("--bin").arg(name),
|
||||
ExecutableType::Lib(name) => cmd.arg("--lib").arg(name),
|
||||
ExecutableType::Example(name) => cmd.arg("--example").arg(name),
|
||||
cargo_args.append(&mut config.cargo_args.clone());
|
||||
|
||||
match &config.executable {
|
||||
ExecutableType::Binary(name) => {
|
||||
cargo_args.push("--bin".to_string());
|
||||
cargo_args.push(name.to_string());
|
||||
}
|
||||
ExecutableType::Lib(name) => {
|
||||
cargo_args.push("--lib".to_string());
|
||||
cargo_args.push(name.to_string());
|
||||
}
|
||||
ExecutableType::Example(name) => {
|
||||
cargo_args.push("--example".to_string());
|
||||
cargo_args.push(name.to_string());
|
||||
}
|
||||
};
|
||||
|
||||
cmd = cmd.args(&cargo_args);
|
||||
let CargoBuildResult {
|
||||
warnings,
|
||||
output_location,
|
||||
} = prettier_build(cmd)?;
|
||||
|
||||
// Start Manganis linker intercept.
|
||||
let linker_args = vec![format!("{}", config.out_dir().display())];
|
||||
|
||||
manganis_cli_support::start_linker_intercept(
|
||||
&LinkCommand::command_name(),
|
||||
cargo_args,
|
||||
Some(linker_args),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let output_location = output_location.context("No output location found")?;
|
||||
|
||||
// [2] Establish the output directory structure
|
||||
@@ -277,7 +299,7 @@ pub fn build_web(
|
||||
|
||||
let assets = if !skip_assets {
|
||||
tracing::info!("Processing assets");
|
||||
let assets = asset_manifest(executable.executable(), config);
|
||||
let assets = asset_manifest(config);
|
||||
process_assets(config, &assets)?;
|
||||
Some(assets)
|
||||
} else {
|
||||
@@ -337,7 +359,9 @@ pub fn build_desktop(
|
||||
build_assets(config)?;
|
||||
let _guard = dioxus_cli_config::__private::save_config(config);
|
||||
let _manganis_support = ManganisSupportGuard::default();
|
||||
let _guard = AssetConfigDropGuard::new();
|
||||
let _asset_guard = AssetConfigDropGuard::new();
|
||||
|
||||
let mut cargo_args = Vec::new();
|
||||
|
||||
let mut cmd = subprocess::Exec::cmd("cargo")
|
||||
.set_rust_flags(rust_flags)
|
||||
@@ -347,38 +371,60 @@ pub fn build_desktop(
|
||||
.arg("--message-format=json-render-diagnostics");
|
||||
|
||||
if config.release {
|
||||
cmd = cmd.arg("--release");
|
||||
cargo_args.push("--release".to_string());
|
||||
}
|
||||
if config.verbose {
|
||||
cmd = cmd.arg("--verbose");
|
||||
cargo_args.push("--verbose".to_string());
|
||||
} else {
|
||||
cmd = cmd.arg("--quiet");
|
||||
cargo_args.push("--quiet".to_string());
|
||||
}
|
||||
|
||||
if config.custom_profile.is_some() {
|
||||
let custom_profile = config.custom_profile.as_ref().unwrap();
|
||||
cmd = cmd.arg("--profile").arg(custom_profile);
|
||||
cargo_args.push("--profile".to_string());
|
||||
cargo_args.push(custom_profile.to_string());
|
||||
}
|
||||
|
||||
if config.features.is_some() {
|
||||
let features_str = config.features.as_ref().unwrap().join(" ");
|
||||
cmd = cmd.arg("--features").arg(features_str);
|
||||
cargo_args.push("--features".to_string());
|
||||
cargo_args.push(features_str);
|
||||
}
|
||||
|
||||
if let Some(target) = &config.target {
|
||||
cmd = cmd.arg("--target").arg(target);
|
||||
cargo_args.push("--target".to_string());
|
||||
cargo_args.push(target.clone());
|
||||
}
|
||||
|
||||
cmd = cmd.args(&config.cargo_args);
|
||||
cargo_args.append(&mut config.cargo_args.clone());
|
||||
|
||||
let cmd = match &config.executable {
|
||||
ExecutableType::Binary(name) => cmd.arg("--bin").arg(name),
|
||||
ExecutableType::Lib(name) => cmd.arg("--lib").arg(name),
|
||||
ExecutableType::Example(name) => cmd.arg("--example").arg(name),
|
||||
match &config.executable {
|
||||
ExecutableType::Binary(name) => {
|
||||
cargo_args.push("--bin".to_string());
|
||||
cargo_args.push(name.to_string());
|
||||
}
|
||||
ExecutableType::Lib(name) => {
|
||||
cargo_args.push("--lib".to_string());
|
||||
cargo_args.push(name.to_string());
|
||||
}
|
||||
ExecutableType::Example(name) => {
|
||||
cargo_args.push("--example".to_string());
|
||||
cargo_args.push(name.to_string());
|
||||
}
|
||||
};
|
||||
|
||||
cmd = cmd.args(&cargo_args);
|
||||
let warning_messages = prettier_build(cmd)?;
|
||||
|
||||
// Start Manganis linker intercept.
|
||||
let linker_args = vec![format!("{}", config.out_dir().display())];
|
||||
|
||||
manganis_cli_support::start_linker_intercept(
|
||||
&LinkCommand::command_name(),
|
||||
cargo_args,
|
||||
Some(linker_args),
|
||||
)?;
|
||||
|
||||
let file_name: String = config.executable.executable().unwrap().to_string();
|
||||
|
||||
let target_file = if cfg!(windows) {
|
||||
@@ -399,7 +445,7 @@ pub fn build_desktop(
|
||||
|
||||
let assets = if !skip_assets {
|
||||
tracing::info!("Processing assets");
|
||||
let assets = asset_manifest(config.executable.executable(), config);
|
||||
let assets = asset_manifest(config);
|
||||
// Collect assets
|
||||
process_assets(config, &assets)?;
|
||||
// Create the __assets_head.html file for bundling
|
||||
|
||||
@@ -16,22 +16,26 @@ pub struct Check {
|
||||
|
||||
impl Check {
|
||||
// Todo: check the entire crate
|
||||
pub async fn check(self) -> Result<()> {
|
||||
match self.file {
|
||||
// Default to checking the project
|
||||
None => {
|
||||
if let Err(e) = check_project_and_report().await {
|
||||
eprintln!("error checking project: {}", e);
|
||||
exit(1);
|
||||
pub fn check(self) -> Result<()> {
|
||||
let rt = tokio::runtime::Runtime::new().unwrap();
|
||||
|
||||
rt.block_on(async move {
|
||||
match self.file {
|
||||
// Default to checking the project
|
||||
None => {
|
||||
if let Err(e) = check_project_and_report().await {
|
||||
eprintln!("error checking project: {}", e);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
Some(file) => {
|
||||
if let Err(e) = check_file_and_report(file).await {
|
||||
eprintln!("failed to check file: {}", e);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
Some(file) => {
|
||||
if let Err(e) = check_file_and_report(file).await {
|
||||
eprintln!("failed to check file: {}", e);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
use crate::{assets, error::Result};
|
||||
use clap::Parser;
|
||||
use std::{fs, path::PathBuf};
|
||||
|
||||
#[derive(Clone, Debug, Parser)]
|
||||
#[clap(name = "link", hide = true)]
|
||||
pub struct LinkCommand {
|
||||
// Allow us to accept any argument after `dx link`
|
||||
#[clap(trailing_var_arg = true, allow_hyphen_values = true)]
|
||||
pub args: Vec<String>,
|
||||
}
|
||||
|
||||
impl LinkCommand {
|
||||
pub fn link(self) -> Result<()> {
|
||||
let Some((link_args, object_files)) = manganis_cli_support::linker_intercept(self.args)
|
||||
else {
|
||||
tracing::warn!("Invalid linker arguments.");
|
||||
return Ok(());
|
||||
};
|
||||
|
||||
// Parse object files, deserialize JSON, & create a file to propogate JSON.
|
||||
let json = manganis_cli_support::get_json_from_object_files(object_files);
|
||||
let parsed = serde_json::to_string(&json).unwrap();
|
||||
|
||||
let out_dir = PathBuf::from(link_args.first().unwrap());
|
||||
fs::create_dir_all(&out_dir).unwrap();
|
||||
|
||||
let path = out_dir.join(assets::MG_JSON_OUT);
|
||||
fs::write(path, parsed).unwrap();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// We need to pass the subcommand name to Manganis so this
|
||||
/// helps centralize where we set the subcommand "name".
|
||||
pub fn command_name() -> String {
|
||||
"link".to_string()
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,7 @@ pub mod clean;
|
||||
pub mod config;
|
||||
pub mod create;
|
||||
pub mod init;
|
||||
pub mod link;
|
||||
pub mod plugin;
|
||||
pub mod serve;
|
||||
pub mod translate;
|
||||
@@ -85,6 +86,10 @@ pub enum Commands {
|
||||
#[cfg(feature = "plugin")]
|
||||
#[clap(subcommand)]
|
||||
Plugin(plugin::Plugin),
|
||||
|
||||
/// Handles parsing of linker arguments for linker-based systems
|
||||
/// such as Manganis and binary patching.
|
||||
Link(link::LinkCommand),
|
||||
}
|
||||
|
||||
impl Display for Commands {
|
||||
@@ -100,6 +105,7 @@ impl Display for Commands {
|
||||
Commands::Autoformat(_) => write!(f, "fmt"),
|
||||
Commands::Check(_) => write!(f, "check"),
|
||||
Commands::Bundle(_) => write!(f, "bundle"),
|
||||
Commands::Link(_) => write!(f, "link"),
|
||||
|
||||
#[cfg(feature = "plugin")]
|
||||
Commands::Plugin(_) => write!(f, "plugin"),
|
||||
|
||||
@@ -15,7 +15,7 @@ pub enum Plugin {
|
||||
}
|
||||
|
||||
impl Plugin {
|
||||
pub async fn plugin(self) -> Result<()> {
|
||||
pub fn plugin(self) -> Result<()> {
|
||||
match self {
|
||||
Plugin::List {} => {
|
||||
for item in crate::plugin::PluginManager::plugin_list() {
|
||||
|
||||
@@ -14,7 +14,7 @@ pub struct Serve {
|
||||
}
|
||||
|
||||
impl Serve {
|
||||
pub async fn serve(self, bin: Option<PathBuf>) -> Result<()> {
|
||||
pub fn serve(self, bin: Option<PathBuf>) -> Result<()> {
|
||||
let mut crate_config = dioxus_cli_config::CrateConfig::new(bin)?;
|
||||
let serve_cfg = self.serve.clone();
|
||||
|
||||
@@ -65,10 +65,10 @@ impl Serve {
|
||||
// start the develop server
|
||||
use server::{desktop, fullstack, web};
|
||||
match platform {
|
||||
Platform::Web => web::startup(crate_config.clone(), &serve_cfg).await?,
|
||||
Platform::Desktop => desktop::startup(crate_config.clone(), &serve_cfg).await?,
|
||||
Platform::Web => web::startup(crate_config.clone(), &serve_cfg)?,
|
||||
Platform::Desktop => desktop::startup(crate_config.clone(), &serve_cfg)?,
|
||||
Platform::Fullstack | Platform::StaticGeneration => {
|
||||
fullstack::startup(crate_config.clone(), &serve_cfg).await?
|
||||
fullstack::startup(crate_config.clone(), &serve_cfg)?
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
#![doc(html_logo_url = "https://avatars.githubusercontent.com/u/79236386")]
|
||||
#![doc(html_favicon_url = "https://avatars.githubusercontent.com/u/79236386")]
|
||||
|
||||
mod assets;
|
||||
pub mod assets;
|
||||
pub mod builder;
|
||||
pub mod server;
|
||||
pub mod tools;
|
||||
|
||||
@@ -10,8 +10,7 @@ use Commands::*;
|
||||
|
||||
const LOG_ENV: &str = "DIOXUS_LOG";
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> anyhow::Result<()> {
|
||||
fn main() -> anyhow::Result<()> {
|
||||
let args = Cli::parse();
|
||||
|
||||
// If {LOG_ENV} is set, default to env, otherwise filter to cli
|
||||
@@ -40,19 +39,17 @@ async fn main() -> anyhow::Result<()> {
|
||||
.context(error_wrapper("Configuring new project failed")),
|
||||
|
||||
#[cfg(feature = "plugin")]
|
||||
Plugin(opts) => opts
|
||||
.plugin()
|
||||
.await
|
||||
.context(error_wrapper("Error with plugin")),
|
||||
Plugin(opts) => opts.plugin().context(error_wrapper("Error with plugin")),
|
||||
|
||||
Autoformat(opts) => opts
|
||||
.autoformat()
|
||||
.context(error_wrapper("Error autoformatting RSX")),
|
||||
|
||||
Check(opts) => opts
|
||||
.check()
|
||||
.await
|
||||
.context(error_wrapper("Error checking RSX")),
|
||||
Check(opts) => opts.check().context(error_wrapper("Error checking RSX")),
|
||||
|
||||
Link(opts) => opts
|
||||
.link()
|
||||
.context(error_wrapper("Error with linker passthrough")),
|
||||
|
||||
action => {
|
||||
let bin = get_bin(args.bin)?;
|
||||
@@ -81,7 +78,6 @@ async fn main() -> anyhow::Result<()> {
|
||||
|
||||
Serve(opts) => opts
|
||||
.serve(Some(bin.clone()))
|
||||
.await
|
||||
.context(error_wrapper("Serving project failed")),
|
||||
|
||||
Bundle(opts) => opts
|
||||
|
||||
@@ -23,11 +23,11 @@ use crate::plugin::PluginManager;
|
||||
|
||||
use super::HotReloadState;
|
||||
|
||||
pub async fn startup(config: CrateConfig, serve: &ConfigOptsServe) -> Result<()> {
|
||||
startup_with_platform::<DesktopPlatform>(config, serve).await
|
||||
pub fn startup(config: CrateConfig, serve: &ConfigOptsServe) -> Result<()> {
|
||||
startup_with_platform::<DesktopPlatform>(config, serve)
|
||||
}
|
||||
|
||||
pub(crate) async fn startup_with_platform<P: Platform + Send + 'static>(
|
||||
pub(crate) fn startup_with_platform<P: Platform + Send + 'static>(
|
||||
config: CrateConfig,
|
||||
serve_cfg: &ConfigOptsServe,
|
||||
) -> Result<()> {
|
||||
@@ -54,7 +54,7 @@ pub(crate) async fn startup_with_platform<P: Platform + Send + 'static>(
|
||||
file_map,
|
||||
};
|
||||
|
||||
serve::<P>(config, serve_cfg, hot_reload_state).await?;
|
||||
serve::<P>(config, serve_cfg, hot_reload_state)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -70,53 +70,55 @@ fn set_ctrl_c(config: &CrateConfig) {
|
||||
}
|
||||
|
||||
/// Start the server without hot reload
|
||||
async fn serve<P: Platform + Send + 'static>(
|
||||
fn serve<P: Platform + Send + 'static>(
|
||||
config: CrateConfig,
|
||||
serve: &ConfigOptsServe,
|
||||
hot_reload_state: HotReloadState,
|
||||
) -> Result<()> {
|
||||
let hot_reload: tokio::task::JoinHandle<Result<()>> = tokio::spawn({
|
||||
let hot_reload_state = hot_reload_state.clone();
|
||||
async move {
|
||||
match hot_reload_state.file_map.clone() {
|
||||
Some(file_map) => {
|
||||
// The open interprocess sockets
|
||||
start_desktop_hot_reload(hot_reload_state, file_map).await?;
|
||||
}
|
||||
None => {
|
||||
std::future::pending::<()>().await;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
});
|
||||
|
||||
let platform = RwLock::new(P::start(&config, serve, Vec::new())?);
|
||||
|
||||
tracing::info!("🚀 Starting development server...");
|
||||
|
||||
// We got to own watcher so that it exists for the duration of serve
|
||||
// Otherwise full reload won't work.
|
||||
let _watcher = setup_file_watcher(
|
||||
{
|
||||
let config = config.clone();
|
||||
let serve = serve.clone();
|
||||
move || {
|
||||
platform
|
||||
.write()
|
||||
.unwrap()
|
||||
.rebuild(&config, &serve, Vec::new())
|
||||
let rt = tokio::runtime::Runtime::new().unwrap();
|
||||
rt.block_on(async move {
|
||||
let hot_reload: tokio::task::JoinHandle<Result<()>> = tokio::spawn({
|
||||
let hot_reload_state = hot_reload_state.clone();
|
||||
async move {
|
||||
match hot_reload_state.file_map.clone() {
|
||||
Some(file_map) => {
|
||||
// The open interprocess sockets
|
||||
start_desktop_hot_reload(hot_reload_state, file_map).await?;
|
||||
}
|
||||
None => {
|
||||
std::future::pending::<()>().await;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
},
|
||||
&config,
|
||||
None,
|
||||
hot_reload_state,
|
||||
)
|
||||
.await?;
|
||||
});
|
||||
|
||||
hot_reload.await.unwrap()?;
|
||||
tracing::info!("🚀 Starting development server...");
|
||||
|
||||
Ok(())
|
||||
// We got to own watcher so that it exists for the duration of serve
|
||||
// Otherwise full reload won't work.
|
||||
let _watcher = setup_file_watcher(
|
||||
{
|
||||
let config = config.clone();
|
||||
let serve = serve.clone();
|
||||
move || {
|
||||
platform
|
||||
.write()
|
||||
.unwrap()
|
||||
.rebuild(&config, &serve, Vec::new())
|
||||
}
|
||||
},
|
||||
&config,
|
||||
None,
|
||||
hot_reload_state,
|
||||
)
|
||||
.await?;
|
||||
|
||||
hot_reload.await.unwrap()?;
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
|
||||
async fn start_desktop_hot_reload(
|
||||
|
||||
@@ -36,8 +36,8 @@ pub fn server_rust_flags(build: &ConfigOptsBuild) -> String {
|
||||
rust_flags(build, SERVER_RUST_FLAGS)
|
||||
}
|
||||
|
||||
pub async fn startup(config: CrateConfig, serve: &ConfigOptsServe) -> Result<()> {
|
||||
desktop::startup_with_platform::<FullstackPlatform>(config, serve).await
|
||||
pub fn startup(config: CrateConfig, serve: &ConfigOptsServe) -> Result<()> {
|
||||
desktop::startup_with_platform::<FullstackPlatform>(config, serve)
|
||||
}
|
||||
|
||||
fn start_web_build_thread(
|
||||
|
||||
@@ -22,7 +22,7 @@ use server::*;
|
||||
|
||||
use super::HotReloadState;
|
||||
|
||||
pub async fn startup(config: CrateConfig, serve_cfg: &ConfigOptsServe) -> Result<()> {
|
||||
pub fn startup(config: CrateConfig, serve_cfg: &ConfigOptsServe) -> Result<()> {
|
||||
set_ctrlc_handler(&config);
|
||||
|
||||
let ip = serve_cfg
|
||||
@@ -33,11 +33,11 @@ pub async fn startup(config: CrateConfig, serve_cfg: &ConfigOptsServe) -> Result
|
||||
|
||||
let hot_reload_state = build_hotreload_filemap(&config);
|
||||
|
||||
serve(ip, config, hot_reload_state, serve_cfg).await
|
||||
serve(ip, config, hot_reload_state, serve_cfg)
|
||||
}
|
||||
|
||||
/// Start the server without hot reload
|
||||
pub async fn serve(
|
||||
pub fn serve(
|
||||
ip: IpAddr,
|
||||
config: CrateConfig,
|
||||
hot_reload_state: HotReloadState,
|
||||
@@ -55,42 +55,45 @@ pub async fn serve(
|
||||
|
||||
tracing::info!("🚀 Starting development server...");
|
||||
|
||||
// We got to own watcher so that it exists for the duration of serve
|
||||
// Otherwise full reload won't work.
|
||||
let _watcher = setup_file_watcher(
|
||||
{
|
||||
let config = config.clone();
|
||||
let hot_reload_state = hot_reload_state.clone();
|
||||
move || build(&config, &hot_reload_state, skip_assets)
|
||||
},
|
||||
&config,
|
||||
Some(WebServerInfo { ip, port }),
|
||||
hot_reload_state.clone(),
|
||||
)
|
||||
.await?;
|
||||
let rt = tokio::runtime::Runtime::new().unwrap();
|
||||
rt.block_on(async move {
|
||||
// We got to own watcher so that it exists for the duration of serve
|
||||
// Otherwise full reload won't work.
|
||||
let _watcher = setup_file_watcher(
|
||||
{
|
||||
let config = config.clone();
|
||||
let hot_reload_state = hot_reload_state.clone();
|
||||
move || build(&config, &hot_reload_state, skip_assets)
|
||||
},
|
||||
&config,
|
||||
Some(WebServerInfo { ip, port }),
|
||||
hot_reload_state.clone(),
|
||||
)
|
||||
.await?;
|
||||
|
||||
// HTTPS
|
||||
// Before console info so it can stop if mkcert isn't installed or fails
|
||||
let rustls_config = get_rustls(&config).await?;
|
||||
// HTTPS
|
||||
// Before console info so it can stop if mkcert isn't installed or fails
|
||||
let rustls_config = get_rustls(&config).await?;
|
||||
|
||||
// Print serve info
|
||||
print_console_info(
|
||||
&config,
|
||||
PrettierOptions {
|
||||
changed: vec![],
|
||||
warnings: first_build_result.warnings,
|
||||
elapsed_time: first_build_result.elapsed_time,
|
||||
},
|
||||
Some(WebServerInfo { ip, port }),
|
||||
);
|
||||
// Print serve info
|
||||
print_console_info(
|
||||
&config,
|
||||
PrettierOptions {
|
||||
changed: vec![],
|
||||
warnings: first_build_result.warnings,
|
||||
elapsed_time: first_build_result.elapsed_time,
|
||||
},
|
||||
Some(WebServerInfo { ip, port }),
|
||||
);
|
||||
|
||||
// Router
|
||||
let router = setup_router(config.clone(), hot_reload_state).await?;
|
||||
// Router
|
||||
let router = setup_router(config.clone(), hot_reload_state).await?;
|
||||
|
||||
// Start server
|
||||
start_server(ip, port, router, opts.open, rustls_config, &config).await?;
|
||||
// Start server
|
||||
start_server(ip, port, router, opts.open, rustls_config, &config).await?;
|
||||
|
||||
Ok(())
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
|
||||
/// Starts dx serve with no hot reload
|
||||
|
||||
Reference in new issue
Block a user