#assets #dioxus

build manganis

Ergonomic, automatic, cross crate asset collection and optimization

34 releases

new 0.7.9 May 8, 2026
0.7.6 Apr 22, 2026
0.7.4 Mar 27, 2026
0.7.2 Dec 5, 2025
0.2.2 Mar 25, 2024

#120 in Build Utils

Download history 15795/week @ 2026-01-19 15264/week @ 2026-01-26 18705/week @ 2026-02-02 15169/week @ 2026-02-09 19848/week @ 2026-02-16 20967/week @ 2026-02-23 22286/week @ 2026-03-02 25925/week @ 2026-03-09 23461/week @ 2026-03-16 25575/week @ 2026-03-23 25078/week @ 2026-03-30 27005/week @ 2026-04-06 31767/week @ 2026-04-13 32660/week @ 2026-04-20 33206/week @ 2026-04-27 30816/week @ 2026-05-04

131,048 downloads per month
Used in 10 crates (7 directly)

MIT/Apache

190KB
3.5K SLoC

Manganis

Manganis is a tool for submitting assets and native source files to the program linker. It makes it easy to self-host assets and native plugins that are distributed throughout your libraries.

Assets

Including assets is as simple as using the asset!() macro:

use manganis::{Asset, asset};
const STYLE: Asset = asset!("/assets/style.css");

After cargo builds your app, the asset path is embedded directly in the data section. A tool like the Dioxus CLI can extract this metadata and post-process these assets.

use manganis::{ImageFormat, Asset, asset, ImageSize, AssetOptions};
// You can collect arbitrary files. Absolute paths are resolved relative to the package root
const _: Asset = asset!("/assets/script.js");

// You can collect images which will be automatically optimized
pub const PNG_ASSET: Asset =
    asset!("/assets/image.png");
// Resize the image at compile time to make the assets smaller
pub const RESIZED_PNG_ASSET: Asset =
    asset!("/assets/image.png", AssetOptions::image().with_size(ImageSize::Manual { width: 52, height: 52 }));
// Or convert the image at compile time to a web friendly format
pub const AVIF_ASSET: Asset = asset!("/assets/image.png", AssetOptions::image().with_format(ImageFormat::Avif));

option_asset

If you have assets that may not always be bundled, you can fall back gracefully with option_asset!:

use manganis::{Asset, asset, option_asset};
const REQUIRED: Asset = asset!("/assets/style.css");
const OPTIONAL: Option<Asset> = option_asset!("/assets/missing.css");

JavaScript assets

The CLI auto-detects whether each .js asset is an ES module (top-level import/export or import.meta) or a classic script and processes it accordingly.

  • with_minify(true) (default): the file is minified in place. Classic scripts are minified verbatim with their format preserved (no IIFE re-wrapping). ES modules are minified and bundled — local relative imports are inlined into a single ESM file, while http:// / https:// imports remain as external import statements for the browser to resolve at runtime.
  • with_minify(false): the file is copied byte-for-byte. Use this when shipping pre-built third-party libraries you do not want re-processed.
  • with_static_head(true): appends a <script> tag to the document head pointing at the asset. The CLI emits <script type="module" ...> when the file is detected (or declared) as an ES module, and a classic <script> otherwise.
  • with_preload(true): emits a <link rel="preload" as="script"> for the asset.
  • with_module(true): forces the file to be treated as an ES module even when auto-detection would say otherwise. Useful when you author a side-effect-only module without top-level import/export declarations. Files named *.mjs are always treated as modules; files named *.cjs are always treated as classic.
use manganis::{asset, Asset, AssetOptions};

// Vendored UMD library: copy verbatim, emitted as a classic <script>.
const SWEETALERT: Asset = asset!(
    "/assets/sweetalert2.all.min.js",
    AssetOptions::js().with_minify(false).with_static_head(true)
);

// Authored ES module with local imports: auto-detected from the top-level
// `import`/`export`, bundled and minified into a single ESM file, emitted as
// `<script type="module">`.
const APP: Asset = asset!(
    "/assets/app.js",
    AssetOptions::js().with_static_head(true)
);

Native FFI Bindings

Manganis provides the #[ffi] attribute macro for generating direct FFI bindings between Rust and native platforms (Swift/Kotlin). See the geolocation-native-plugin example for usage.

Dependencies

~1–13MB
~106K SLoC