Skip to content

Commit 9d4ece4

Browse files
timsaucerjprochazk
andauthored
Series of build changes for web release to minimize generated wasm (#9870)
Co-authored-by: jprochazk <[email protected]> Co-authored-by: Jan Procházka <[email protected]>
1 parent 6336229 commit 9d4ece4

File tree

5 files changed

+45
-15
lines changed

5 files changed

+45
-15
lines changed

Cargo.toml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -394,6 +394,13 @@ opt-level = 2
394394
# debug = true # good for profilers
395395
panic = "abort" # This leads to better optimizations and smaller binaries (and is the default in Wasm anyways).
396396

397+
[profile.web-release]
398+
panic = 'abort' # Removes panic handling code
399+
inherits = "release"
400+
lto = true
401+
opt-level = 'z' # Optimize for size
402+
codegen-units = 1
403+
397404

398405
## Bench
399406

crates/build/re_dev_tools/src/build_web_viewer/lib.rs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,14 +32,14 @@ fn target_directory() -> Utf8PathBuf {
3232

3333
#[derive(Clone, Copy, PartialEq, Eq)]
3434
pub enum Profile {
35-
Release,
35+
WebRelease,
3636
Debug,
3737
}
3838

3939
impl Profile {
4040
pub fn as_str(&self) -> &'static str {
4141
match self {
42-
Self::Release => "release",
42+
Self::WebRelease => "web-release",
4343
Self::Debug => "debug",
4444
}
4545
}
@@ -126,8 +126,8 @@ pub fn build(
126126
if !features.is_empty() {
127127
cmd.arg(format!("--features={features}"));
128128
}
129-
if profile == Profile::Release {
130-
cmd.arg("--release");
129+
if profile == Profile::WebRelease {
130+
cmd.arg("--profile=web-release");
131131
}
132132

133133
// This is required for unstable WebGPU apis to work
@@ -200,7 +200,7 @@ pub fn build(
200200
);
201201
}
202202

203-
if profile == Profile::Release {
203+
if profile == Profile::WebRelease {
204204
eprintln!("Optimizing wasm with wasm-opt…");
205205
let start_time = Instant::now();
206206

@@ -213,9 +213,12 @@ pub fn build(
213213
"--output",
214214
wasm_path.as_str(),
215215
"--enable-reference-types",
216+
"--vacuum",
216217
];
217218
if debug_symbols {
218219
args.push("-g");
220+
} else {
221+
args.push("--strip-debug");
219222
}
220223
cmd.args(args);
221224
eprintln!("{root_dir}> {cmd:?}");

crates/build/re_dev_tools/src/build_web_viewer/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ fn default_features() -> String {
5050

5151
pub fn main(args: Args) -> anyhow::Result<()> {
5252
let profile = if args.release && !args.debug {
53-
Profile::Release
53+
Profile::WebRelease
5454
} else if !args.release && args.debug {
5555
Profile::Debug
5656
} else {

pixi.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,7 @@ rerun-web-release = { cmd = "cargo run --package rerun-cli --no-default-features
198198
#
199199
# This installs the `wasm32-unknown-unknown` rust target if it's not already installed.
200200
# (this looks heavy but takes typically below 0.1s!)
201-
rerun-build-web-release = "rustup target add wasm32-unknown-unknown && cargo run --quiet -p re_dev_tools -- build-web-viewer --no-default-features --features analytics,map_view --release -g"
201+
rerun-build-web-release = "rustup target add wasm32-unknown-unknown && cargo run --quiet -p re_dev_tools -- build-web-viewer --no-default-features --features analytics,map_view --release"
202202

203203
rs-check = { cmd = "rustup target add wasm32-unknown-unknown && python scripts/ci/rust_checks.py", depends-on = [
204204
"rerun-build-web", # The checks require the web viewer wasm to be around.

rerun_js/web-viewer/build-wasm.mjs

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,12 @@ function re_viewer_js() {
5757
const end = `wasm_bindgen = Object.assign(__wbg_init, { initSync }, __exports);
5858
5959
})();`;
60+
if (code.indexOf(start) === -1) {
61+
throw new Error("failed to run js build script: failed to patch re_viewer.js, could not find replace start marker");
62+
}
63+
if (code.indexOf(end) === -1) {
64+
throw new Error("failed to run js build script: failed to patch re_viewer.js, could not find replace end marker");
65+
}
6066
code = code.replace(start, "").replace(end, "");
6167

6268
code = `
@@ -66,10 +72,11 @@ ${code}
6672
function deinit() {
6773
__wbg_init.__wbindgen_wasm_module = null;
6874
wasm = null;
75+
cachedUint8ArrayMemory0 = null;
6976
cachedFloat32ArrayMemory0 = null;
7077
cachedInt32ArrayMemory0 = null;
7178
cachedUint32ArrayMemory0 = null;
72-
cachedUint8ArrayMemory0 = null;
79+
cachedDataViewMemory0 = null;
7380
}
7481
7582
return Object.assign(__wbg_init, { initSync, deinit }, __exports);
@@ -80,19 +87,32 @@ return Object.assign(__wbg_init, { initSync, deinit }, __exports);
8087
// Otherwise we end up with an exceptioon during closure destruction which prevents the references from all being
8188
// cleaned up properly.
8289
// TODO(jprochazk): Can we force these to run before we null `wasm` instead?
83-
const closure_dtors = `const CLOSURE_DTORS = (typeof FinalizationRegistry === 'undefined')
84-
? { register: () => {}, unregister: () => {} }
85-
: new FinalizationRegistry(state => {
86-
wasm.__wbindgen_export_4.get(state.dtor)(state.a, state.b)
87-
});`;
90+
const closure_dtors_start_marker = "const CLOSURE_DTORS";
91+
const closure_dtors_end_marker = "});";
92+
93+
const closure_dtors_start = code.indexOf(closure_dtors_start_marker);
94+
if (closure_dtors_start === -1) {
95+
throw new Error("failed to run js build script: failed to patch re_viewer.js, could not find CLOSURE_DTORS start");
96+
}
97+
const closure_dtors_end = code.indexOf(closure_dtors_end_marker, closure_dtors_start);
98+
if (closure_dtors_end === -1) {
99+
throw new Error("failed to run js build script: failed to patch re_viewer.js, could not find CLOSURE_DTORS end");
100+
}
101+
102+
let m = code.substring(closure_dtors_start, closure_dtors_end).match(/__wbindgen_export_\d+/);
103+
if (!m) {
104+
throw new Error("failed to run js build script: failed to patch re_viewer.js, could not find __wbindgen_export within CLOSURE_DTORS");
105+
}
106+
107+
let wbindgen_export = m[0];
88108

89109
const closure_dtors_patch = `const CLOSURE_DTORS = (typeof FinalizationRegistry === 'undefined')
90110
? { register: () => {}, unregister: () => {} }
91111
: new FinalizationRegistry(state => {
92-
wasm?.__wbindgen_export_4.get(state.dtor)(state.a, state.b)
112+
wasm?.${wbindgen_export}.get(state.dtor)(state.a, state.b)
93113
});`;
94114

95-
code = code.replace(closure_dtors, closure_dtors_patch);
115+
code = code.substring(0, closure_dtors_start) + closure_dtors_patch + code.slice(closure_dtors_end + closure_dtors_end_marker.length);
96116

97117
fs.writeFileSync(path.join(__dirname, "re_viewer.js"), code);
98118
}

0 commit comments

Comments
 (0)