Optimize wasm examples for the website (#8636)

# Objective

- Improve speed of loading examples on the website
- Triggered by https://news.ycombinator.com/item?id=35996393

## Solution

- Use wasm-opt to optimize files for size. This reduces the files from
22mb to 13mb
- Cloudflare doesn't set the correct `Content-Type` header by default
for wasm files, add it manually. This enables wasm streaming and
compression, dropping the transfer to 3.9mb

The files with this script are deployed on
optimized.wasm-pages.pages.dev if you want to test, you can replace this
URL on a website deployed locally.
This commit is contained in:
François 2023-05-19 19:57:54 +02:00 committed by GitHub
parent 25f013ba1b
commit e944b0a3a5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 62 additions and 12 deletions

View file

@ -29,6 +29,10 @@ struct Args {
#[arg(value_enum, short, long, default_value_t = Api::Webgl2)]
/// Browser API to use for rendering
api: Api,
#[arg(short, long)]
/// Optimize the wasm file for size with wasm-opt
optimize_size: bool,
}
fn main() {
@ -89,7 +93,7 @@ fn main() {
}
let mut cmd = cmd!(
sh,
"cargo build {parameters...} --release --target wasm32-unknown-unknown --example {example}"
"cargo build {parameters...} --profile release --target wasm32-unknown-unknown --example {example}"
);
if matches!(cli.api, Api::Webgpu) {
cmd = cmd.env("RUSTFLAGS", "--cfg=web_sys_unstable_apis");
@ -103,6 +107,11 @@ fn main() {
.run()
.expect("Error creating wasm binding");
if cli.optimize_size {
cmd!(sh, "wasm-opt -Oz --output examples/wasm/target/wasm_example_bg.wasm.optimized examples/wasm/target/wasm_example_bg.wasm")
.run().expect("Failed to optimize for size. Do you have wasm-opt corretly set up?");
}
if cli.test {
let _dir = sh.push_dir(".github/start-wasm-example");
let mut browsers = cli.browsers.clone();

View file

@ -11,3 +11,4 @@ xshell = "0.2"
clap = { version = "4.0", features = ["derive"] }
ron = "0.8"
toml_edit = "0.19"
pbr = "1.1"

View file

@ -9,6 +9,7 @@ use std::{
};
use clap::Parser;
use pbr::ProgressBar;
use toml_edit::Document;
use xshell::{cmd, Shell};
@ -53,6 +54,10 @@ enum Action {
#[arg(long)]
/// Enable hacks for Bevy website integration
website_hacks: bool,
#[arg(long)]
/// Optimize the wasm file for size with wasm-opt
optimize_size: bool,
},
}
@ -175,7 +180,6 @@ header_message = \"Examples (WebGPU)\"
.unwrap();
let mut categories = HashMap::new();
for to_show in examples_to_run {
if !to_show.wasm {
continue;
@ -248,6 +252,7 @@ header_message = \"Examples (WebGPU)\"
Action::BuildWebGPUExamples {
content_folder,
website_hacks,
optimize_size,
} => {
let examples_to_build = parse_examples();
@ -256,6 +261,17 @@ header_message = \"Examples (WebGPU)\"
let _ = fs::create_dir_all(root_path);
if website_hacks {
// setting up the headers file for cloudflare for the correct Content-Type
let mut headers = File::create(root_path.join("_headers")).unwrap();
headers
.write_all(
"/*/wasm_example_bg.wasm
Content-Type: application/wasm
"
.as_bytes(),
)
.unwrap();
let sh = Shell::new().unwrap();
// setting a canvas by default to help with integration
@ -266,6 +282,12 @@ header_message = \"Examples (WebGPU)\"
cmd!(sh, "sed -i.bak 's/asset_folder: \"assets\"/asset_folder: \"\\/assets\\/examples\\/\"/' crates/bevy_asset/src/lib.rs").run().unwrap();
}
let mut pb = ProgressBar::new(
examples_to_build
.iter()
.filter(|to_build| to_build.wasm)
.count() as u64,
);
for to_build in examples_to_build {
if !to_build.wasm {
continue;
@ -273,12 +295,21 @@ header_message = \"Examples (WebGPU)\"
let sh = Shell::new().unwrap();
let example = &to_build.technical_name;
if optimize_size {
cmd!(
sh,
"cargo run -p build-wasm-example -- --api webgpu {example} --optimize-size"
)
.run()
.unwrap();
} else {
cmd!(
sh,
"cargo run -p build-wasm-example -- --api webgpu {example}"
)
.run()
.unwrap();
}
let category_path = root_path.join(&to_build.category);
let _ = fs::create_dir_all(&category_path);
@ -295,11 +326,20 @@ header_message = \"Examples (WebGPU)\"
Path::new("examples/wasm/target/wasm_example.js"),
&example_path.join("wasm_example.js"),
);
if optimize_size {
let _ = fs::rename(
Path::new("examples/wasm/target/wasm_example_bg.wasm.optimized"),
&example_path.join("wasm_example_bg.wasm"),
);
} else {
let _ = fs::rename(
Path::new("examples/wasm/target/wasm_example_bg.wasm"),
&example_path.join("wasm_example_bg.wasm"),
);
}
pb.inc();
}
pb.finish_print("done");
}
}
}