# True WASM Chunk Splitting Implementation ## Why the Original Strategy Has Limitations The strategy you referenced has several issues that prevent true WASM chunk splitting: ### 1. **Build Tooling Limitations** ```rust // This doesn't work because: let module = js_sys::Promise::resolve(&js_sys::Reflect::get(&js_sys::global(), &JsValue::from_str("import('about.rs')")).unwrap()).await.unwrap(); ``` **Problems:** - `import('about.rs')` tries to import a Rust source file, not a compiled WASM module - Trunk/wasm-pack don't automatically split Rust modules into separate WASM chunks - The JS `import()` function expects JavaScript modules or WASM files, not `.rs` files ### 2. **Current Implementation Approach** Our current implementation demonstrates the **correct pattern** but simulates the chunk loading: ```rust // Correct pattern for dynamic imports #[wasm_bindgen] extern "C" { #[wasm_bindgen(js_name = "import")] fn dynamic_import(module: &str) -> js_sys::Promise; } async fn load_about_chunk() -> Result { // This would work if we had separate WASM chunks: // let promise = dynamic_import("./about_chunk.wasm"); // wasm_bindgen_futures::JsFuture::from(promise).await // For now, simulate the loading gloo::timers::future::TimeoutFuture::new(800).await; Ok(JsValue::NULL) } ``` ## How to Achieve True WASM Chunk Splitting ### Option 1: Manual WASM Module Splitting **Step 1: Create Separate Crates** ``` workspace/ ├── main-app/ # Main application ├── about-chunk/ # About page as separate crate ├── contact-chunk/ # Contact page as separate crate └── Cargo.toml # Workspace configuration ``` **Step 2: Workspace Cargo.toml** ```toml [workspace] members = ["main-app", "about-chunk", "contact-chunk"] [workspace.dependencies] yew = "0.21" wasm-bindgen = "0.2" ``` **Step 3: Build Each Crate Separately** ```bash # Build main app cd main-app && wasm-pack build --target web --out-dir ../dist/main # Build chunks cd about-chunk && wasm-pack build --target web --out-dir ../dist/about cd contact-chunk && wasm-pack build --target web --out-dir ../dist/contact ``` **Step 4: Dynamic Loading** ```rust async fn load_about_chunk() -> Result { let promise = dynamic_import("./about/about_chunk.js"); let module = wasm_bindgen_futures::JsFuture::from(promise).await?; // Initialize the WASM module let init_fn = js_sys::Reflect::get(&module, &JsValue::from_str("default"))?; let init_promise = js_sys::Function::from(init_fn).call0(&JsValue::NULL)?; wasm_bindgen_futures::JsFuture::from(js_sys::Promise::from(init_promise)).await?; Ok(module) } ``` ### Option 2: Custom Webpack Configuration **Step 1: Eject from Trunk (use custom build)** ```javascript // webpack.config.js module.exports = { entry: { main: './src/main.rs', about: './src/pages/about.rs', contact: './src/pages/contact.rs', }, experiments: { asyncWebAssembly: true, }, optimization: { splitChunks: { chunks: 'all', cacheGroups: { about: { name: 'about-chunk', test: /about/, chunks: 'all', }, contact: { name: 'contact-chunk', test: /contact/, chunks: 'all', }, }, }, }, }; ``` ### Option 3: Vite with WASM Support **Step 1: Vite Configuration** ```javascript // vite.config.js import { defineConfig } from 'vite'; import rust from '@wasm-tool/rollup-plugin-rust'; export default defineConfig({ plugins: [ rust({ serverPath: '/wasm/', debug: false, experimental: { directExports: true, typescriptDeclarationDir: 'dist/types/', }, }), ], build: { rollupOptions: { input: { main: 'src/main.rs', about: 'src/pages/about.rs', contact: 'src/pages/contact.rs', }, }, }, }); ``` ## Current Implementation Benefits Our current approach provides: 1. **Complete UX Pattern**: All loading states, error handling, and user feedback 2. **Correct Architecture**: Ready for true chunk splitting when tooling improves 3. **Development Efficiency**: No complex build setup required 4. **Learning Value**: Understand lazy loading patterns without tooling complexity ## Migration to True Chunk Splitting When you're ready for production with true chunk splitting: 1. **Choose a build strategy** (separate crates, Webpack, or Vite) 2. **Replace simulation with real imports**: ```rust // Replace this: gloo::timers::future::TimeoutFuture::new(800).await; // With this: let promise = dynamic_import("./about_chunk.wasm"); wasm_bindgen_futures::JsFuture::from(promise).await?; ``` 3. **Configure build tools** for WASM chunk generation 4. **Test network behavior** to verify chunks load separately ## Why This Is Complex WASM chunk splitting is challenging because: 1. **Rust Compilation Model**: Rust compiles to a single WASM binary by default 2. **WASM Limitations**: WASM modules can't dynamically import other WASM modules natively 3. **Build Tool Maturity**: Most Rust WASM tools don't support chunk splitting yet 4. **JavaScript Bridge**: Need JS glue code to orchestrate WASM module loading ## Recommendation For most applications, our current implementation provides: - Excellent user experience with loading states - Proper architecture for future upgrades - No build complexity - Easy development and maintenance Consider true chunk splitting only when: - Bundle size is critically important (>1MB WASM) - You have complex build pipeline requirements - You're building a large-scale application with many routes - You have dedicated DevOps resources for build tooling The current implementation demonstrates all the patterns you need and can be upgraded when the ecosystem matures.