Skip to content

Commit

Permalink
docs: reorganize deployment section (#2036)
Browse files Browse the repository at this point in the history
* Update mdbook-admonish book dependency

* Move "Optimizing Binary Size" to Deploy.. chapter

* Minor text updates to the Deployment section
  • Loading branch information
diversable authored Nov 17, 2023
1 parent 362e3bc commit 414f5fc
Show file tree
Hide file tree
Showing 6 changed files with 87 additions and 93 deletions.
1 change: 1 addition & 0 deletions docs/book/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,4 @@ mdbook serve
```

It should be available at `http://localhost:3000`.

2 changes: 1 addition & 1 deletion docs/book/book.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,4 @@ runnable = false

[preprocessor.admonish]
command = "mdbook-admonish"
assets_version = "2.0.2" # do not edit: managed by `mdbook-admonish install`
assets_version = "3.0.1" # do not edit: managed by `mdbook-admonish install`
166 changes: 79 additions & 87 deletions docs/book/mdbook-admonish.css

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions docs/book/src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@
- [Responses and Redirects](./server/27_response.md)
- [Progressive Enhancement and Graceful Degradation](./progressive_enhancement/README.md)
- [`<ActionForm/>`s](./progressive_enhancement/action_form.md)
- [Deployment](./deployment.md)
- [Deployment](./deployment/README.md)
- [Optimizing WASM Binary Size](./deployment/binary_size.md)
- [Guide: Islands](./islands.md)
- [Appendix: How Does the Reactive System Work?](./appendix_reactive_graph.md)
- [Appendix: Optimizing WASM Binary Size](./appendix_binary_size.md)
- [Appendix: Some Small DX Improvements](./appendix_dx.md)
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ There are as many ways to deploy a web application as there are developers, let

1. Remember: Always deploy Rust apps built in `--release` mode, not debug mode. This has a huge effect on both performance and binary size.
2. Test locally in release mode as well. The framework applies certain optimizations in release mode that it does not apply in debug mode, so it’s possible for bugs to surface at this point. (If your app behaves differently or you do encounter a bug, it’s likely a framework-level bug and you should open a GitHub issue with a reproduction.)
3. See the chapter on "Optimizing WASM Binary Size" for additional tips and tricks to further improve the time-to-interactive metric for your WASM app on first load.

> We asked users to submit their deployment setups to help with this chapter. I’ll quote from them below, but you can read the full thread [here](https://github.com/leptos-rs/leptos/issues/1152).
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Appendix: Optimizing WASM Binary Size
# Optimizing WASM Binary Size

One of the primary downsides of deploying a Rust/WebAssembly frontend app is that splitting a WASM file into smaller chunks to be dynamically loaded is significantly more difficult than splitting a JavaScript bundle. There have been experiments like [`wasm-split`](https://emscripten.org/docs/optimizing/Module-Splitting.html) in the Emscripten ecosystem but at present there’s no way to split and dynamically load a Rust/`wasm-bindgen` binary. This means that the whole WASM binary needs to be loaded before your app becomes interactive. Because the WASM format is designed for streaming compilation, WASM files are much faster to compile per kilobyte than JavaScript files. (For a deeper look, you can [read this great article from the Mozilla team](https://hacks.mozilla.org/2018/01/making-webassembly-even-faster-firefoxs-new-streaming-and-tiering-compiler/) on streaming WASM compilation.)

Expand Down Expand Up @@ -59,13 +59,13 @@ And you'll need to add `panic = "abort"` to `[profile.release]` in `Cargo.toml`.

## Things to Avoid

There are certain crates that tend to inflate binary sizes. For example, the `regex` crate with its default features adds about 500kb to a WASM binary (largely because it has to pull in Unicode table data!) In a size-conscious setting, you might consider avoiding regexes in general, or even dropping down and calling browser APIs to use the built-in regex engine instead. (This is what `leptos_router` does on the few occasions it needs a regular expression.)
There are certain crates that tend to inflate binary sizes. For example, the `regex` crate with its default features adds about 500kb to a WASM binary (largely because it has to pull in Unicode table data!). In a size-conscious setting, you might consider avoiding regexes in general, or even dropping down and calling browser APIs to use the built-in regex engine instead. (This is what `leptos_router` does on the few occasions it needs a regular expression.)

In general, Rust’s commitment to runtime performance is sometimes at odds with a commitment to a small binary. For example, Rust monomorphizes generic functions, meaning it creates a distinct copy of the function for each generic type it’s called with. This is significantly faster than dynamic dispatch, but increases binary size. Leptos tries to balance runtime performance with binary size considerations pretty carefully; but you might find that writing code that uses many generics tends to increase binary size. For example, if you have a generic component with a lot of code in its body and call it with four different types, remember that the compiler could include four copies of that same code. Refactoring to use a concrete inner function or helper can often maintain performance and ergonomics while reducing binary size.

## A Final Thought

Remember that in a server-rendered app, JS bundle size/WASM binary size affects only _one_ thing: time to interactivity on the first load. This is very important to a good user experiencenobody wants to click a button three times and have it do nothing because the interactive code is still loadingbut it is not the only important measure.
Remember that in a server-rendered app, JS bundle size/WASM binary size affects only _one_ thing: time to interactivity on the first load. This is very important to a good user experience: nobody wants to click a button three times and have it do nothing because the interactive code is still loadingbut it's not the only important measure.

It’s especially worth remembering that streaming in a single WASM binary means all subsequent navigations are nearly instantaneous, depending only on any additional data loading. Precisely because your WASM binary is _not_ bundle split, navigating to a new route does not require loading additional JS/WASM, as it does in nearly every JavaScript framework. Is this copium? Maybe. Or maybe it’s just an honest trade-off between the two approaches!

Expand Down

0 comments on commit 414f5fc

Please sign in to comment.