DioxusLabs / DioxusLabs/dioxus
asset!() re-encodes PNG by default and significantly increases file size
- Dominant language
- Rust
- Stars
- 39.1k
- Forks
- 1.9k
- Avg merge
- 4d 10h
- Merged PRs (30d)
- 4
Description
## 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:
```text
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:
```text
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:
```text
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:
```rust
img {
src: asset!("public/assets/forest-background.png")
}
```
Image transcoding/resizing/re-encoding should only happen when explicitly requested with something like:
```rust
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:
```text
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:
```bash
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:
```text
public/assets/forest-background.png
```
3. Reference it through `asset!()`:
```rust
use dioxus::prelude::*;
fn App() -> Element {
rsx! {
img {
src: asset!("public/assets/forest-background.png")
}
}
}
```
4. Build the app:
```bash
rm -rf dist target/dx
dx bundle --platform web --release --out-dir dist
```
5. Compare the source and output file sizes:
```bash
ls -lh public/assets/forest-background.png
find dist/public/assets -maxdepth 1 -name "*forest-background*" -exec ls -lh {} \;
```
## Observed result
```text
public/assets/forest-background.png 193K
dist/public/assets/forest-background.png 976K
dist/public/assets/forest-background-dxh...png 976K
```
## Environment
```text
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:
```text
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:
Contributor guide
No contributing guide indexed for this repository
Research direction
Start by reproducing the issue with the provided asset! example and `dx bundle --platform web --release --out-dir dist`, then trace how asset! inputs are handled during bundling. Compare the source and generated PNG bytes and sizes. Done means the default path preserves the original bytes while explicit image processing remains opt-in.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- build-system, web-dev
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 62/100