Build Configuration

Overview of Tauri v2 build configuration covering production preparation, build optimization, and platform-specific requirements for React plus Vite frontends

A Tauri app that runs on your machine with tauri dev is not yet ready for other people to use. Development mode prioritizes fast feedback — hot reloading, unoptimized bundles, debug symbols, and a dev server that serves your frontend. Shipping to users requires a different set of priorities: small binaries, fast startup, and the guarantee that the app will run on a machine that does not have Node.js, Rust, or any development tool installed.

Build configuration is the bridge between those two modes. It lives across two files — tauri.conf.json for frontend wiring and Cargo.toml for Rust compilation — and it touches every platform you intend to target. The decisions you make here determine how large your final binary is, how quickly it launches, and whether it works at all on a given operating system.

What Build Configuration Covers

The build configuration for a Tauri v2 app spans three connected areas, each with its own detailed page in this section.

Preparing for Production is about telling Tauri where your frontend assets are, what command builds them, and how the frontend and Rust backend connect when there is no dev server running. A misconfigured frontendDist path or a missing beforeBuildCommand is the most common reason a Tauri build fails silently or produces an app that shows a blank window.

Optimizing Builds moves into the Rust compilation pipeline. The default Cargo build settings favor compile speed over output quality. For a shipping application, you want the opposite: the smallest possible binary that runs as fast as the compiler can make it. This means configuring link-time optimization, stripping debug symbols, and choosing the right optimization level — all in Cargo.toml.

Platform Requirements is the reality check. Each operating system your app targets needs specific system libraries installed on the build machine. Linux requires webkit2gtk-4.1 and several other packages. Windows needs the WebView2 runtime and the MSVC build tools. macOS requires Xcode. Missing any of these does not produce a polite error message — the build simply fails with linker errors that are hard to decipher if you have not seen them before.

These three areas are not sequential steps you complete one after another. They overlap and interact. A build optimization that works on macOS might break the Linux build if it strips something the linker needs. A platform dependency installed on your CI runner might be the wrong version for your target distribution. The detailed pages in this section walk through each area, but the overview that follows gives you the mental model to understand how they fit together.

The Configuration File

Build configuration in Tauri v2 centers on the tauri.conf.json file inside the src-tauri/ directory. This file is generated when you run tauri init and contains four top-level objects: app, build, bundle, and plugins. The build object is what controls how Tauri locates, builds, and assembles your frontend with the Rust backend.

src-tauri/tauri.conf.json
{
  "productName": "my-tauri-app",
  "version": "0.1.0",
  "build": {
    "beforeBuildCommand": "npm run build",
    "beforeDevCommand": "npm run dev",
    "devUrl": "http://localhost:1420",
    "frontendDist": "../dist"
  },
  "app": {
    "security": {
      "csp": null
    },
    "windows": [
      {
        "title": "My Tauri App",
        "width": 800,
        "height": 600
      }
    ]
  },
  "bundle": {},
  "plugins": {}
}

Four fields inside build control the frontend integration. beforeDevCommand is the shell command Tauri runs when you execute tauri dev — it starts your Vite development server. devUrl tells Tauri where that server is listening so it can point the webview at it. beforeBuildCommand is what runs when you execute tauri build — it compiles your React app into static files. frontendDist tells Tauri where those compiled files land so it can embed them into the final binary.

Incorrect frontendDist Path:

The frontendDist path is relative to the src-tauri/ directory, not the project root. For a standard Vite project where output goes to a top-level dist/ folder, the correct value is ../dist. Using dist or ./dist will cause the build to fail with an error about not finding an index.html file. This is the single most common build configuration mistake.

Tauri also supports platform-specific configuration files that merge with the main config. If you create a tauri.windows.conf.json, tauri.linux.conf.json, or tauri.macos.conf.json alongside the main config, Tauri reads it and overlays its values on top of the base configuration. This lets you set different beforeBuildCommand values or window settings per platform without duplicating the entire file.

Alternative Configuration Formats:

By default, Tauri uses JSON for configuration. If you enable the config-json5 or config-toml Cargo features, you can write the configuration in JSON5 (tauri.conf.json or tauri.conf.json5) or TOML (Tauri.toml). The structure is identical — only the syntax changes. JSON remains the recommended format unless your team already uses TOML for other Rust project configuration.

The Three Areas of Build Configuration

Each of the three nested pages in this section covers one area in depth. What follows is an overview of what each area addresses, why it matters, and what you should understand before reading the detailed guide.

Preparing for Production

Development and production builds use fundamentally different strategies to serve the frontend. In development, Tauri opens a webview and points it at http://localhost:1420 — your Vite dev server. The frontend code is served from memory, rebuilt on every file change, and never touches the filesystem. This is fast for development but requires Node.js, the Vite binary, and your entire node_modules folder to be present and running.

In production, none of that exists. The frontend must be compiled into static HTML, CSS, and JavaScript files ahead of time, and those files must be physically present on disk so Tauri can embed them into the Rust binary. The beforeBuildCommand field is what bridges this gap. For a React + Vite project, it is typically npm run build, which runs vite build and outputs static files to the dist/ folder. The frontendDist field then points Tauri to that folder.

Forgetting the beforeBuildCommand:

If beforeBuildCommand is empty or incorrect, Tauri runs tauri build without compiling the frontend first. If stale build artifacts exist in frontendDist, Tauri embeds them — producing an app with outdated frontend code. If no artifacts exist at all, the build fails. Always verify that running your beforeBuildCommand manually produces a complete set of static files in the directory that frontendDist points to.

The distinction between devUrl and frontendDist is worth internalizing early. devUrl is used only during tauri dev and points to a running server. frontendDist is used only during tauri build and points to static files on disk. They serve the same purpose — telling Tauri where the frontend is — but they operate in completely different contexts. Confusing the two is a common source of "works in dev, broken in production" scenarios.

For the full walkthrough of setting up a production-ready build, including handling environment variables, cache busting, and verifying the output, see the Preparing for Production page.

Optimizing Builds

The Rust compiler, by default, optimizes for compile speed during development. It produces binaries with debug symbols, skips aggressive inlining, and compiles each crate independently to allow incremental recompilation. This is exactly what you want when you are iterating — fast cargo build times matter more than binary size.

For a shipping application, the priorities invert. Users care about download size, launch time, and memory usage. They do not care how long the CI pipeline took. Configuring the [profile.release] section in src-tauri/Cargo.toml tells the Rust compiler to spend more time compiling in exchange for a smaller, faster binary.

src-tauri/Cargo.toml
[profile.release]
codegen-units = 1
lto = "fat"
opt-level = "z"
panic = "abort"
strip = true

Each of these settings trades compile time for output quality. codegen-units = 1 tells the compiler to optimize the entire crate as a single unit, which enables more inlining and dead code elimination but eliminates parallel code generation. lto = "fat" performs link-time optimization across all dependencies, not just your code — the linker can strip unused functions from libraries you depend on. opt-level = "z" prioritizes binary size over speed, which is generally the right tradeoff for desktop apps where download size matters more than microbenchmarks. panic = "abort" removes the panic unwinding machinery, shrinking the binary. strip = true removes debug symbols entirely.

Correctly Configured Release Profile:

If your Cargo.toml includes the five settings shown above, your release builds are configured for production. You can verify the configuration without going through a full build pipeline by compiling only the backend. ary size — it should be noticeably smaller than a default release build. On a typical Tauri + React project, the difference between default release settings and the optimized profile can be substantial, often cutting the binary size in half or more.

Beyond the Rust compiler, Tauri itself provides a build optimization: the removeUnusedCommands setting in tauri.conf.json. When set to true, Tauri analyzes your frontend code and removes any Rust commands that are never called from JavaScript. This is a tree-shaking pass at the IPC boundary — if you registered a command but never invoke it, it does not ship in the final binary.

The Optimizing Builds page covers these settings in detail, including when opt-level = "s" might be a better choice than "z", how to measure binary size improvements, and the interaction between Tauri's bundler and the Rust compiler optimizations.

Platform Requirements

Every Tauri app embeds a system webview to render the frontend. On Linux, that webview is WebKitGTK. On Windows, it is WebView2. On macOS, it is WKWebView. Each of these requires specific system libraries to be present on the machine that compiles the app — not just the machine that runs it.

For Linux, the critical dependency is webkit2gtk-4.1. Tauri v2 specifically requires the 4.1 version of the library, which uses libsoup3 for HTTP networking. Older distributions that ship only webkit2gtk-4.0 (which uses libsoup2) cannot build Tauri v2 applications natively. This is a deliberate change from Tauri v1 and affects which Linux distributions can serve as build hosts.

On Ubuntu 22.04 or later, install the required packages:

sudo apt update
sudo apt install -y libwebkit2gtk-4.1-dev libappindicator3-dev \
  librsvg2-dev patchelf libssl-dev libgtk-3-dev \
  libsoup-3.0-dev libjavascriptcoregtk-4.1-dev

For Fedora 37 or later, the equivalent command uses dnf:

sudo dnf install -y webkit2gtk4.1-devel libappindicator-gtk3-devel \
  librsvg2-devel patchelf openssl-devel gtk3-devel \
  libsoup3-devel javascriptcoregtk4.1-devel

Distribution Compatibility:

Tauri v2 requires webkit2gtk-4.1, which is available on Ubuntu 22.04+, Debian 12+, and Fedora 37+. Older enterprise distributions like RHEL 9 / CentOS Stream 9 ship glib2 2.68, which is too old for the libsoup3 dependency. If you must target older Linux distributions, consider distributing via Flatpak, which bundles its own runtime and sidesteps system library version requirements.

The platform you build on does not have to match the platform you target — cross-compilation is possible for some combinations. Building Windows installers from Linux works using cargo-xwin, which provides the MSVC toolchain without requiring a Windows license. Building for macOS from Linux or Windows is not supported due to Apple's tooling restrictions. The Platform Requirements page covers every supported build host and target combination, including CI runner configurations.

Missing System Dependencies:

A build that fails with linker errors mentioning webkit2gtk, WebView2, or webkit almost always means the platform dependencies are missing or are the wrong version. On Linux, check that pkg-config can find the library with pkg-config --modversion webkit2gtk-4.1. On Windows, verify the MSVC build tools are installed and that rustup show lists x86_64-pc-windows-msvc as an installed target. These checks catch the vast majority of platform-related build failures before you spend time debugging linker output.

Putting It Together

A typical production build sequence for a Tauri v2 app with a React + Vite frontend looks like this:

1

Step 1: Verify the Frontend Build

Before running tauri build, confirm that your frontend compiles correctly on its own. Run your beforeBuildCommand manually and check that the frontendDist directory contains an index.html file and the compiled assets.

npm run build
ls dist/  # should show index.html, assets/, and other static files

If this step fails or produces an empty output directory, Tauri will embed nothing and your app will show a blank white window. Fix frontend build issues before moving to Tauri's build step.

2

Step 2: Configure tauri.conf.json

Set the build object to match your project structure. For a standard Vite project, the configuration is straightforward but every field must be correct:

src-tauri/tauri.conf.json
{
  "build": {
    "beforeBuildCommand": "npm run build",
    "beforeDevCommand": "npm run dev",
    "devUrl": "http://localhost:1420",
    "frontendDist": "../dist"
  }
}

The port in devUrl must match the port Vite uses — check your vite.config.ts if you changed it from the default 1420.

3

Step 3: Configure Cargo.toml for Release

Add or update the [profile.release] section in src-tauri/Cargo.toml with the optimization settings covered in the Optimizing Builds section. This step can be done once and committed to version control — it does not change between builds.

src-tauri/Cargo.toml
[profile.release]
codegen-units = 1
lto = "fat"
opt-level = "z"
panic = "abort"
strip = true
4

Step 4: Install Platform Dependencies

On a fresh build machine, install the system libraries for each platform you target. If you are building on the same machine you develop on, these are likely already installed. If you are setting up CI, this step must be part of the workflow.

Refer to the platform-specific installation commands in the Platform Requirements section above for the exact packages your build host needs.

5

Step 5: Run the Production Build

Execute tauri build from your project root. Tauri will run beforeBuildCommand, compile the Rust backend with the release profile, embed the frontend assets, and produce platform-specific installers in src-tauri/target/release/bundle/.

npm run tauri build

If all previous steps were configured correctly, the output will include a .msi or .exe installer on Windows, a .dmg on macOS, and a .deb, .rpm, or .AppImage on Linux — depending on your bundle configuration.

Summary

Build configuration in Tauri v2 is the set of decisions that turn a project that works on your machine into an application that works on anyone's machine. It spans two ecosystems — JavaScript for the frontend pipeline and Rust for the compiled backend — and it requires awareness of what each target operating system needs from the build host.

The most common failure modes all trace back to one of three root causes: the frontend is not being compiled before Tauri tries to embed it, the Rust compiler is producing unnecessarily large or slow binaries because the release profile was never configured, or the build machine is missing a system library that the target platform requires. Each of these has a straightforward fix once you know what to look for.

The detailed pages that follow — Preparing for Production, Optimizing Builds, and Platform Requirements — walk through each area with concrete configuration examples, troubleshooting guidance, and platform-specific instructions. If you are setting up a project for the first time, work through them in order. If you are debugging a specific build failure, jump directly to the page that matches your symptoms.

Preparing for Production

Configure your Tauri app's identity, icons, resources, and external binaries to build distributable production packages.

Optimizing Builds

Techniques for reducing Tauri v2 binary size, improving performance, and managing build-time trade-offs in a React plus Vite frontend

Platform Requirements

What your operating system needs to compile and bundle Tauri v2 desktop applications, with specific setup instructions for Windows, macOS, and Linux.