Reducing the App Size
At Tauri, we are working on reducing the environmental footprint of applications by using system resources where available, providing compiled systems that don't need runtime evaluation, and offering guides so that engineers can go even smaller without sacrificing on performance or security. The point is, by saving resources, we are doing our part to help you help us save the planet -- which is the only bottom line that companies in the 21st Century should care about.
So if you are interested in learning how to improve your app size and performance, read on, dear friend:
You can't improve what you can't measure
Before you can optimize your app, you need to figure out what takes up space in your app! Here are a couple of tools that can assist you with that:
cargo-bloatis a rust utility to determine what takes the most space in your app. It gives you an excellent, sorted overview of the most significant rust functions.
You noticed a dependency included in your final frontend bundle, but you are unsure why?
rollup-plugin-graphgenerates graphviz compatible visualizations of your entire dependency graph.
These are just a couple of tools that you might use. Make sure to check your frontend bundlers plugin list for more!
Think twice before adding a dependency
- Reducing the App Size
- You can't improve what you can't measure
- Think twice before adding a dependency
- 2. Optimize Dependencies
- 3. Optimize Images
- 4. Remove Unnecessary Custom Fonts
- 5. Allowlist Config
- 6. Rust Build-time Optimizations
- 7. Stripping
- 8. UPX
Enable tree shaking
Minification removes unnecessary whitespace, shortens variable names, and applies other optimizations. Most bundlers enable this by default; a notable exception is rollup, where you need plugins like rollup-plugin-terser or rollup-plugin-uglify.
Disable source maps
2. Optimize Dependencies
Many popular libraries have smaller and faster alternatives that you can choose instead.
Most libraries you use depend on many libraries themselves, so a library that looks inconspicuous at first glance might add several megabytes worth of code to your app.
If you find a library that seems excessively large, google around, chances are someone else already had the same thought and created an alternative. A good example is Moment.js and it's Many alternatives.
But keep in mind: The best dependency is no dependency, meaning that you should always prefer language builtins over 3rd party packages.
3. Optimize Images
You can choose between a variety of manual options (GIMP, Photoshop, Squoosh) or plugins for your favorite frontend build tools (vite-imagetools, vite-plugin-imagemin, image-minimizer-webpack-plugin).
imagemin library most of the plugins use is officially unmaintained.
Use modern image formats
Formats such as
avifoffer size reductions of up to 95% compared to jpeg while maintaining excellent visual accuracy. You can use tools such as Squoosh to try different formats on your images.
Size images accordingly
No one appreciates you shipping the 6K raw image with your app, so make sure to size your image accordingly. Images that appear large on-screen should be sized larger than images that take up less screen space.
Don't use Responsive Images
In a Web Environment, you are supposed to use Responsive Images to load the correct image size for each user dynamically. You are not building a simple website, though: All your images are already downloaded. So using Responsive Images only bloat your app with redundant copies.
Images that were taken straight from a camera or stock photo side often include metadata about the Camera and Lens model or Photographer. Not only are those wasted bytes, but metadata properties can also hold potentially sensitive information such as the time, day, and location of the photo.
4. Remove Unnecessary Custom Fonts
Consider not shipping custom fonts with your app and relying on system fonts instead. If you must ship custom fonts, make sure they are in modern, optimized formats such as
Fonts can be pretty big, so using the fonts already included in the Operating System reduces the footprint of your app. It also avoids FOUT (Flash of Unstyled Text) and makes your app feel more "native" since it uses the same font as all other apps.
If you must include custom fonts, make sure you include them in modern formats such as
woff2 as those tend to be way smaller than legacy formats.
Use so-called "System Font Stacks" in your CSS. There are a number of variations, but here are 3 basic ones to get you started:
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial,
sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji';
font-family: Iowan Old Style, Apple Garamond, Baskerville, Times New Roman, Droid
Serif, Times, Source Serif Pro, serif, Apple Color Emoji, Segoe UI Emoji, Segoe
font-family: ui-monospace, SFMono-Regular, SF Mono, Menlo, Consolas, Liberation
5. Allowlist Config
You can reduce the size of your app by only enabling the Tauri API features you need in the
allowlist config determines what API features to enable; disabled features will not be compiled into your app. This is an easy way of shedding some extra weight.
An example from a typical
6. Rust Build-time Optimizations
Configure your cargo project to take advantage of rusts size optimization features. Why is a rust executable large ? provides an excellent explanation on why this matters and an in-depth walkthrough. At the same time, Minimizing Rust Binary Size is more up-to-date and has a couple of extra recommendations.
Rust is notorious for producing large binaries, but you can instruct the compiler to optimize the final executable's size.
Cargo exposes several options that determine how the compiler generates your binary. The "recommended" options for Tauri apps are these:
panic = "abort" # Strip expensive panic clean-up logic
codegen-units = 1 # Compile crates one after another so the compiler can optimize better
lto = true # Enables link to optimizations
opt-level = "s" # Optimize for binary size
There is also
opt-level = "z" available to reduce the resulting binary size.
"z" can sometimes be smaller than the other, so test it with your application!
We've seen smaller binary sizes from
"s" for Tauri example applications, but real-world applications can always differ.
For a detailed explanation of each option and a bunch more, refer to the Cargo books Profiles section.
Unstable Rust Compression Features
The following suggestions are all unstable features and require a nightly toolchain. See the Unstable Features documentation for more information on what this involves.
The following methods involve using unstable compiler features and require the rust nightly toolchain. If you don't have the nightly toolchain +
rust-src nightly component added, try the following:
rustup toolchain install nightly
rustup component add rust-src --toolchain nightly
The Rust Standard Library comes precompiled. This means rust is faster to install, but also that the compiler can't optimize the Standard Library. You can apply the optimization options for the rest of your binary + dependencies to the std with an unstable flag. This flag requires specifying your target, so know the target triple you are targeting.
cargo +nightly build --release -Z build-std --target x86_64-unknown-linux-gnu
If you are using
panic = "abort" in your release profile optimizations, you need to make sure the
panic_abort crate is compiled with std. Additionally, an extra std feature can further reduce the binary size. The following applies both:
cargo +nightly build --release -Z build-std=std,panic_abort -Z build-std-features=panic_immediate_abort --target x86_64-unknown-linux-gnu
Use strip utilities to remove debug symbols from your compiled app.
Your compiled app includes so-called "Debug Symbols" that include function and variable names. Your end-users will probably not care about Debug Symbols, so this is a pretty surefire way to save some bytes!
The easiest way is to use the famous
strip utility to remove this debugging information.
See your local
strip manpage for more information and flags that can be used to specify what information gets stripped out from the binary.
UPX, Ultimate Packer for eXecutables, is a dinosaur amongst the binary packers. This 23-year old, well-maintained piece of kit is GPL-v2 licensed with a pretty liberal usage declaration. Our understanding of the licensing is that you can use it for any purposes (commercial or otherwise) without needing to change your license unless you modify the source code of UPX.
Maybe your target audience has very slow internet, or your app needs to fit on a tiny USB stick, and all the above steps haven't resulted in the savings you need. Fear not, as we have one last trick up our sleeves:
UPX compresses your binary and creates a self-extracting executable that decompresses itself at runtime.
You should know that this technique might flag your binary as a virus on Windows and macOS - so use at your own discretion, and as always, validate with Frida and do real distribution testing!
Usage on macOS
brew install upx
yarn tauri build
upx --ultra-brute src-tauri/target/release/bundle/macos/app.app/Contents/macOS/app
Ultimate Packer for eXecutables
Copyright (C) 1996 - 2018
UPX 3.95 Markus Oberhumer, Laszlo Molnar & John Reiser Aug 26th 2018
File size Ratio Format Name
-------------------- ------ ----------- -----------
963140 -> 274448 28.50% macho/amd64 app