Skip to content

asset!() re-encodes PNG by default and significantly increases file size #5642

Description

@gekh

Description

In a Dioxus 0.7 web app, PNG assets included via asset!() appear to be re-encoded by default during dx bundle.

This can significantly increase the size of already optimized production images.

For example, in my project:

public/assets/forest-background.png        193K
dist/public/assets/forest-background.png   976K
dist/public/assets/forest-background-dxh...png 976K

The same problem happens with other optimized PNG files:

public/assets/forest-background-winter.png        224K
dist/public/assets/forest-background-winter.png   806K

public/assets/satchel-background-winter.png       212K
dist/public/assets/satchel-background-winter.png  1.1M

The main issue is that asset!() appears to optimize/re-encode images by default, but for already optimized PNGs this makes the files much larger.

Expected behavior

By default, asset!() should not change image bytes.

I would expect asset!() to:

1. copy/bundle the asset
2. optionally hash the filename
3. preserve the original file bytes unless image processing is explicitly requested

In other words, this should preserve the original optimized PNG:

img {
    src: asset!("public/assets/forest-background.png")
}

Image transcoding/resizing/re-encoding should only happen when explicitly requested with something like:

AssetOptions::image()
    .with_format(...)
    .with_size(...)

or another explicit optimization option.

Actual behavior

asset!() re-encodes PNG files by default, and the output PNG can become much larger than the source PNG.

Example:

source:
-rw-r--r--  public/assets/forest-background.png        193K

after dx bundle:
-rw-r--r--  dist/public/assets/forest-background.png   976K
-rw-r--r--  dist/public/assets/forest-background-dxh...png 976K

This is surprising because the original file is already optimized and no explicit image conversion/resizing was requested.

Build command

We build the app with:

dx bundle --platform web --release --out-dir dist

Steps to reproduce

  1. Create a Dioxus 0.7 web app.
  2. Place an already optimized PNG file in:
public/assets/forest-background.png
  1. Reference it through asset!():
use dioxus::prelude::*;

fn App() -> Element {
    rsx! {
        img {
            src: asset!("public/assets/forest-background.png")
        }
    }
}
  1. Build the app:
rm -rf dist target/dx
dx bundle --platform web --release --out-dir dist
  1. Compare the source and output file sizes:
ls -lh public/assets/forest-background.png
find dist/public/assets -maxdepth 1 -name "*forest-background*" -exec ls -lh {} \;

Observed result

public/assets/forest-background.png        193K
dist/public/assets/forest-background.png   976K
dist/public/assets/forest-background-dxh...png 976K

Environment

Dioxus CLI: 0.7.9
Dioxus crate: 0.7.9
Platform: web
Build command: dx bundle --platform web --release --out-dir dist
Local OS: macOS arm64
CI OS: Ubuntu GitHub Actions

Why this matters

This can heavily increase production bundle size and bandwidth usage.

For games and visual apps, many PNG assets are already manually optimized. A build tool silently re-encoding them by default can make the production output much worse.

A safer default would be:

asset!() = bundle/hash/copy without changing bytes
AssetOptions::image() = explicit image processing

Question

Is this behavior intended?

If yes, is there a documented way to disable image re-encoding for selected PNG assets?

If no, I think this should be treated as a bug or at least a problematic default behavior.

Example image attached:
Image

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingcliRelated to the dioxus-cli programgood first issueGood for newcomersmanganisRelated to the manganis crate

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions