Skip to content

Commit

Permalink
kinda sorta works with the cli
Browse files Browse the repository at this point in the history
  • Loading branch information
jkelleyrtp committed Feb 4, 2025
1 parent b224358 commit 821b65c
Show file tree
Hide file tree
Showing 20 changed files with 190 additions and 75 deletions.
11 changes: 0 additions & 11 deletions .cargo/config.toml

This file was deleted.

2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

28 changes: 12 additions & 16 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -65,14 +65,6 @@ members = [
"packages/const-serialize-macro",
"packages/dx-wire-format",
"packages/logger",

# Playwright tests
"packages/playwright-tests/liveview",
"packages/playwright-tests/web",
"packages/playwright-tests/fullstack",
"packages/playwright-tests/suspense-carousel",
"packages/playwright-tests/nested-suspense",

# manganis
"packages/manganis/manganis",
"packages/manganis/manganis-core",
Expand All @@ -82,7 +74,6 @@ members = [
"packages/wasm-split/wasm-split",
"packages/wasm-split/wasm-split-macro",
"packages/wasm-split/wasm-split-cli",
"packages/wasm-split/wasm-split-harness",

# Full project examples
"example-projects/fullstack-hackernews",
Expand All @@ -107,6 +98,7 @@ members = [
"packages/playwright-tests/suspense-carousel",
"packages/playwright-tests/nested-suspense",
"packages/playwright-tests/cli-optimization",
"packages/playwright-tests/wasm-split-harness",
]

[workspace.package]
Expand Down Expand Up @@ -159,7 +151,7 @@ manganis-macro = { path = "packages/manganis/manganis-macro", version = "0.6.2"
wasm-split = { path = "packages/wasm-split/wasm-split", version = "0.1.0" }
wasm-split-macro = { path = "packages/wasm-split/wasm-split-macro", version = "0.1.0" }
wasm-split-cli = { path = "packages/wasm-split/wasm-split-cli", version = "0.1.0" }
wasm-split-harness = { path = "packages/wasm-split/wasm-split-harness", version = "0.1.0" }
wasm-split-harness = { path = "packages/playwright-tests/wasm-split-harness", version = "0.1.0" }

warnings = { version = "0.2.1" }

Expand Down Expand Up @@ -259,24 +251,28 @@ debug = 0

# our release profile should be fast to compile and fast to run
# when we ship our CI builds, we turn on LTO which improves perf leftover by turning on incremental
[profile.release]
incremental = true
debug = 0
# [profile.release]
# incremental = true
# debug = 0

[profile.release-max-opt]
inherits = "release"
# incremental = true
[profile.release]
lto = true
codegen-units = 1
opt-level = 'z'
strip = "debuginfo"

# Disable debug assertions to check the released path of core and other packages, but build without optimizations to keep build times quick
[profile.release-unoptimized]
inherits = "dev"
debug-assertions = false
incremental = true

[profile.dev.package."*"]
opt-level = 3

[profile.wasm-dev]
inherits = "dev"
opt-level = 1

[profile.server-dev]
inherits = "dev"
Expand Down
2 changes: 2 additions & 0 deletions packages/cli-opt/src/js.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,8 @@ fn bundle_js_to_writer_inside_handler(
let mut entries = HashMap::default();
entries.insert("main".to_string(), FileName::Real(file));

tracing::debug!("Bundle entries: {:?}", entries);

let mut bundles = bundler
.bundle(entries)
.context("failed to bundle javascript with swc")?;
Expand Down
1 change: 1 addition & 0 deletions packages/cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ dioxus-cli-config = { workspace = true }
dioxus-cli-opt = { workspace = true }
dioxus-fullstack = { workspace = true }
dioxus-dx-wire-format = { workspace = true }
wasm-split-cli = { workspace = true }

clap = { workspace = true, features = ["derive", "cargo"] }
convert_case = { workspace = true }
Expand Down
113 changes: 100 additions & 13 deletions packages/cli/src/build/bundle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use anyhow::Context;
use dioxus_cli_opt::{process_file_to, AssetManifest};
use manganis::{AssetOptions, JsAssetOptions};
use rayon::prelude::{IntoParallelRefIterator, ParallelIterator};
use std::collections::HashSet;
use std::collections::{HashMap, HashSet};
use std::future::Future;
use std::path::{Path, PathBuf};
use std::pin::Pin;
Expand Down Expand Up @@ -331,10 +331,18 @@ impl AppBundle {
self.run_wasm_bindgen(&self.app.exe.with_extension("wasm"))
.await?;

// Only run wasm-opt if the feature is enabled
// Wasm-opt has an expensive build script that makes it annoying to keep enabled for iterative dev
// We put it behind the "wasm-opt" feature flag so that it can be disabled when iterating on the cli
self.run_wasm_opt(&self.build.exe_dir())?;
if self.build.build.experimental_bundle_split {
self.run_bundle_split().await?;
}

// self.hash_wasm_bindgen_assets()?;

// else {
// // Only run wasm-opt if the feature is enabled
// // Wasm-opt has an expensive build script that makes it annoying to keep enabled for iterative dev
// // We put it behind the "wasm-opt" feature flag so that it can be disabled when iterating on the cli
// self.run_wasm_opt(&self.build.exe_dir())?;
// }

// Write the index.html file with the pre-configured contents we got from pre-rendering
std::fs::write(
Expand Down Expand Up @@ -486,8 +494,8 @@ impl AppBundle {
.await
.map_err(|e| anyhow::anyhow!("A task failed while trying to copy assets: {e}"))??;

// Remove the wasm bindgen output directory if it exists
_ = std::fs::remove_dir_all(self.build.wasm_bindgen_out_dir());
// // Remove the wasm bindgen output directory if it exists
// _ = std::fs::remove_dir_all(self.build.wasm_bindgen_out_dir());

// Write the version file so we know what version of the optimizer we used
std::fs::write(
Expand Down Expand Up @@ -636,21 +644,31 @@ impl AppBundle {
.wasm_bindgen_version()
.expect("this should have been checked by tool verification");

let keep_debug = true;
let demangle = false;
let keep_lld_sections = true;

WasmBindgen::new(&bindgen_version)
.input_path(&input_path)
.target("web")
.debug(keep_debug)
.demangle(keep_debug)
.demangle(demangle)
.keep_debug(keep_debug)
.remove_name_section(!keep_debug)
.remove_producers_section(!keep_debug)
// .remove_name_section(!keep_debug)
// .remove_producers_section(!keep_debug)
.keep_lld_sections(keep_lld_sections)
.out_name(&name)
.out_dir(&bindgen_outdir)
.run()
.await
.context("Failed to generate wasm-bindgen bindings")?;

// After running wasm-bindgen, add the js and wasm asset to the manifest
tracing::debug!(dx_src = ?TraceSrc::Bundle, "wasm-bindgen complete in {:?}", start.elapsed());

Ok(())
}

fn hash_wasm_bindgen_assets(&mut self) -> Result<(), anyhow::Error> {
let js_output_path = self.build.wasm_bindgen_js_output_file();
let wasm_output_path = self.build.wasm_bindgen_wasm_output_file();
let new_assets = [
Expand All @@ -660,6 +678,7 @@ impl AppBundle {
),
(wasm_output_path, AssetOptions::Unknown),
];

for (asset_path, options) in new_assets {
let hash = manganis_core::hash::AssetHash::hash_file_contents(&asset_path)?;
let output_path_str = asset_path.to_str().ok_or(anyhow::anyhow!(
Expand All @@ -673,8 +692,6 @@ impl AppBundle {
self.app.assets.assets.insert(asset_path, bundled_asset);
}

tracing::debug!(dx_src = ?TraceSrc::Bundle, "wasm-bindgen complete in {:?}", start.elapsed());

Ok(())
}

Expand Down Expand Up @@ -725,6 +742,76 @@ impl AppBundle {
Ok(())
}

async fn run_bundle_split(&mut self) -> Result<()> {
let bindgen_dir = self.build.wasm_bindgen_out_dir();
let prebindgen = self.app.exe.clone();
let post_bindgen = self.build.wasm_bindgen_wasm_output_file();
let original = std::fs::read(&prebindgen)?;
let bindgened = std::fs::read(&post_bindgen)?;

tracing::info!(
"Running wasm-split. Old: {:?}, New: {:?}",
prebindgen,
post_bindgen
);
// tokio::task::spawn_blocking(move || {
let splitter = wasm_split_cli::Splitter::new(&original, &bindgened)
.context("Failed to parse wasm for splitter")?;
let mut modules = splitter.emit()?;

tracing::debug!(
"wasm-split emitted {} modules with {} chunks",
modules.modules.len(),
modules.chunks.len()
);

let mut new_assets = vec![];

// Overwrite the original wasm with the split wasm
std::fs::write(&post_bindgen, modules.main.bytes)?;
new_assets.push((post_bindgen, AssetOptions::Unknown));

// Write the modules
// todo(jon): pass these through manganis? need to add a hash
for (idx, module) in modules.modules.iter().enumerate() {
let path = format!(
"module_{}_{}.wasm",
idx,
module.component_name.as_ref().unwrap()
);
tracing::debug!("Writing split module {}", path);
std::fs::write(bindgen_dir.join(&path), &module.bytes)?;
new_assets.push((bindgen_dir.join(path), AssetOptions::Unknown));
}

// Write the chunks
for (idx, chunk) in modules.chunks.iter().enumerate() {
let path = format!("chunk_{}_{}.wasm", idx, chunk.module_name);
tracing::debug!("Writing split chunk {}", path);
std::fs::write(bindgen_dir.join(&path), &chunk.bytes)?;
new_assets.push((bindgen_dir.join(path), AssetOptions::Unknown));
}

// Write the wasm chunks
let mut renamed_chunks = HashMap::new();
for (asset_path, options) in new_assets {
let hash = manganis_core::hash::AssetHash::hash_file_contents(&asset_path)
.context("Failed to hash file")?;
let output_path_str = asset_path.to_str().ok_or(anyhow::anyhow!(
"Failed to convert wasm bindgen output path to string"
))?;
let bundled_asset = manganis::macro_helpers::create_bundled_asset(
output_path_str,
hash.bytes(),
options,
);
renamed_chunks.insert(asset_path.clone(), bundled_asset.bundled_path().to_string());
self.app.assets.assets.insert(asset_path, bundled_asset);
}

Ok(())
}

async fn pre_render_ssg_routes(&self) -> Result<()> {
// Run SSG and cache static routes
if !self.build.build.ssg {
Expand Down
7 changes: 6 additions & 1 deletion packages/cli/src/build/request.rs
Original file line number Diff line number Diff line change
Expand Up @@ -340,6 +340,11 @@ impl BuildRequest {

cargo_args.push(self.krate.executable_name().to_string());

if self.build.platform() == Platform::Web {
cargo_args.push("--".to_string());
cargo_args.push("-Clink-args=--emit-relocs".to_string());
}

tracing::debug!(dx_src = ?TraceSrc::Build, "cargo args: {:?}", cargo_args);

cargo_args
Expand Down Expand Up @@ -658,7 +663,7 @@ impl BuildRequest {

/// Get the path to the wasm bindgen temporary output folder
pub fn wasm_bindgen_out_dir(&self) -> PathBuf {
self.root_dir().join("wasm-bindgen")
self.root_dir().join("wasm")
}

/// Get the path to the wasm bindgen javascript output file
Expand Down
13 changes: 7 additions & 6 deletions packages/cli/src/build/web.rs
Original file line number Diff line number Diff line change
Expand Up @@ -143,12 +143,13 @@ impl AppBundle {
r#"<script>
// We can't use a module script here because we need to start the script immediately when streaming
import("/{base_path}/{js_path}").then(
({ default: init }) => {
init("/{base_path}/{wasm_path}").then((wasm) => {
if (wasm.__wbindgen_start == undefined) {
wasm.main();
}
});
({ default: init, initSync }) => {
window.initSync = initSync;
init("/{base_path}/{wasm_path}").then((wasm) => {
if (wasm.__wbindgen_start == undefined) {
wasm.main();
}
});
}
);
</script>
Expand Down
4 changes: 4 additions & 0 deletions packages/cli/src/cli/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@ pub(crate) struct BuildArgs {
#[clap(long, default_value_t = true)]
pub(crate) inject_loading_scripts: bool,

/// Experimental: Bundle split the wasm binary into multiple chunks based on `#[wasm_split]` annotations [default: false]
#[clap(long, default_value_t = false)]
pub(crate) experimental_bundle_split: bool,

/// Generate debug symbols for the wasm binary [default: true]
///
/// This will make the binary larger and take longer to compile, but will allow you to debug the
Expand Down
3 changes: 2 additions & 1 deletion packages/cli/src/dioxus_crate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -364,7 +364,8 @@ impl DioxusCrate {
/// Check if assets should be pre_compressed. This will only be true in release mode if the user
/// has enabled pre_compress in the web config.
pub(crate) fn should_pre_compress_web_assets(&self, release: bool) -> bool {
self.config.web.pre_compress && release
false
// self.config.web.pre_compress
}

// The `opt-level=1` increases build times, but can noticeably decrease time
Expand Down
Loading

0 comments on commit 821b65c

Please sign in to comment.