-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
New default compilation profiles for web commands (#199)
# Objective Closes #197. The `bevy build web` and `bevy run web` commands currently use the same default profiles as the `cargo` commands, so either `dev` or `release` if the `--release` flag is provided. However, the demands of web apps can be vastly different than native apps when it comes to compilation. For example, it's a lot more effective to optimize for low binary size on the web, because it significantly reduces the loading time of the app. This causes two problems with the current implementation: - The defaults are bad. If the user doesn't know about the differences, they will probably have high loading times for their apps or potentially longer compile times. - Fixing the problem results in boilerplate. Once you set up custom profiles for a better configuration, you will have to provide the `--profile={profile_name}` argument *every* time you execute `bevy run web`... which is both a hassle and easy to forget. # Solution The web commands now use the `web` or `web-release` profiles by default. This means we can provide better defaults, while still allowing the user to fully customize the configuration (by just defining these profiles themselves in `Cargo.toml`). It also means the user doesn't have to pass the `--profile` flag to the web commands, in most cases. Of course, by default there won't be any definitions for the `web` and `web-release` profiles and we don't want to edit the user's `Cargo.toml` directly. So if we configured `--profile=web` we would get an error. We circumvent this problem with [`--config` flag overrides](https://doc.rust-lang.org/cargo/reference/config.html#command-line-overrides), which essentially allow you to add additional entries to the `Cargo.toml`. For example, `--config profile.web.inherits="dev"` allows us to add the `web` profile. It can be further customized with default settings in a similar way. I just set up very basic default configurations for the new profiles, optimizing them will be a task for a future PR.
- Loading branch information
1 parent
d6034dd
commit d5f6bf7
Showing
10 changed files
with
157 additions
and
26 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,6 @@ | ||
//! Utilities for building and running the app in the browser. | ||
pub(crate) mod bundle; | ||
pub(crate) mod profiles; | ||
#[cfg(feature = "wasm-opt")] | ||
pub(crate) mod wasm_opt; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
use std::{collections::HashMap, fs}; | ||
|
||
use anyhow::Context as _; | ||
use toml_edit::DocumentMut; | ||
|
||
use crate::external_cli::{arg_builder::ArgBuilder, cargo::metadata::Metadata}; | ||
|
||
/// Create `--config` args to configure the default profiles to use when compiling for the web. | ||
pub(crate) fn configure_default_web_profiles(metadata: &Metadata) -> anyhow::Result<ArgBuilder> { | ||
let manifest = fs::read_to_string(metadata.workspace_root.join("Cargo.toml")) | ||
.context("failed to read workspace manifest")? | ||
.parse::<DocumentMut>() | ||
.context("failed to parse workspace manifest")?; | ||
|
||
let mut args = ArgBuilder::new(); | ||
|
||
if !is_profile_defined_in_manifest(&manifest, "web") { | ||
args = args.append(configure_web_profile()); | ||
} | ||
|
||
if !is_profile_defined_in_manifest(&manifest, "web-release") { | ||
args = args.append(configure_web_release_profile()); | ||
} | ||
|
||
Ok(args) | ||
} | ||
|
||
fn is_profile_defined_in_manifest(manifest: &DocumentMut, profile: &str) -> bool { | ||
manifest | ||
.get("profile") | ||
.is_some_and(|profiles| profiles.get(profile).is_some()) | ||
} | ||
|
||
/// Configure the default profile for web debug builds. | ||
/// | ||
/// It is optimized for fast iteration speeds. | ||
fn configure_web_profile() -> ArgBuilder { | ||
configure_profile("web", "dev", HashMap::new()) | ||
} | ||
|
||
/// Configure the default profile for web release builds. | ||
/// | ||
/// It is optimized both for run time performance and loading times. | ||
fn configure_web_release_profile() -> ArgBuilder { | ||
let config = HashMap::from_iter([ | ||
// Optimize for size, greatly reducing loading times | ||
("opt-level", "s"), | ||
// Remove debug information, reducing file size further | ||
("strip", "debuginfo"), | ||
]); | ||
configure_profile("web-release", "release", config) | ||
} | ||
|
||
/// Create `--config` args for `cargo` to configure a new compilation profile. | ||
/// | ||
/// Equivalent to a `Cargo.toml` like this: | ||
/// | ||
/// ```toml | ||
/// [profile.{profile}] | ||
/// inherits = "{inherits}" | ||
/// # config | ||
/// key = "value" | ||
/// ``` | ||
fn configure_profile(profile: &str, inherits: &str, config: HashMap<&str, &str>) -> ArgBuilder { | ||
let mut args = ArgBuilder::new().add_with_value( | ||
"--config", | ||
format!(r#"profile.{profile}.inherits="{inherits}""#), | ||
); | ||
|
||
for (key, value) in config { | ||
args = args.add_with_value("--config", format!(r#"profile.{profile}.{key}="{value}""#)); | ||
} | ||
|
||
args | ||
} | ||
|
||
#[cfg(test)] | ||
mod tests { | ||
use super::*; | ||
|
||
#[test] | ||
fn should_detect_defined_profile() { | ||
let manifest = r#" | ||
[profile.web] | ||
inherits = "dev" | ||
"# | ||
.parse() | ||
.unwrap(); | ||
|
||
assert!(is_profile_defined_in_manifest(&manifest, "web")); | ||
} | ||
|
||
#[test] | ||
fn should_detect_missing_profile() { | ||
let manifest = r#" | ||
[profile.foo] | ||
inherits = "dev" | ||
"# | ||
.parse() | ||
.unwrap(); | ||
|
||
assert!(!is_profile_defined_in_manifest(&manifest, "web")); | ||
} | ||
} |