Skip to content

Add loading bar to web template#740

Open
CorvusPrudens wants to merge 3 commits intoTheBevyFlock:mainfrom
CorvusPrudens:loading-bar
Open

Add loading bar to web template#740
CorvusPrudens wants to merge 3 commits intoTheBevyFlock:mainfrom
CorvusPrudens:loading-bar

Conversation

@CorvusPrudens
Copy link

@CorvusPrudens CorvusPrudens commented Feb 20, 2026

Bevy's Wasm binaries frequently come in at 20+ MBs, even after compression. Depending on the speed of the server or a user's internet connection, downloads can take quite a while. Without any concrete indication of progress, some users get frustrated and leave.

With small changes, we can introduce a progress bar for the Wasm download phase.

Screenshot 2026-02-17 at 9 01 14 PM

Technical considerations

Since we can't rely on the Content-Length header for the size of the Wasm,1 we need to embed the size into the HTML ahead of time. We also need the URL for both the generated JS and Wasm, since we need to fetch the Wasm binary directly. Consequently, this PR introduces two new template parameters. This potentially introduces more points of failure and some additional maintenance burden.

This also brings the role of the default index.html into question. Should is serve as a barebones starting point for Bevy users, or should it provide the best UX we can manage within reason?

Having participated in Bevy Jam 7, I believe the latter is a better direction to strive for. To my knowledge, every team that used the CLI made no changes to the default template. Among other issues, the slow downloads contributed to a somewhat poor experience playing these games in the browser. With a few changes, including this PR, I think we'll give both devs and players a much better impression of Bevy as a whole.

Details

I'm not attached to the exact visual presentation of this PR. Maybe the spinner should be removed when we have the length information. Maybe the bytes should actually just be a percentage. The main purpose here is to propose that we take this direction in one form or another.

Also, I acknowledge the effort on the CLI will largely be focused on upstreaming via the new goals, so this may sit around for a while. I plan to make some other UX improvements in the meantime.

Footnotes

  1. A resource's Content-Length header doesn't reflect its full size when compressed, and may even be omitted entirely. Since the fetch API only provides uncompressed chunks when using a ReadableStream, the Content-Length won't match the chunks when transfer encoding is applied. Thus, you need to know the size of the uncompressed resource if you want accurate progress.

import init from "./build/bevy_app.js";
init().catch((error) => {
const wasmPath = "./build/bevy_app_bg.wasm";
const wasmSize = null;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reading this by itself is quite confusing. I wonder if we need a more visual indicator for the template replacement, especially so that users can use it for their custom index files.

But that issue existed before, so it probably makes sense to tackle it in a different PR

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The three calls to replace are also rather ugly in the Rust code.

<noscript>JavaScript support is required to run this app</noscript>
<div id="loading-screen" class="center">
<span class="spinner"></span>
<div hidden="hidden" class="bar-container">
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm a fan of semantic HTML, which is also more accessible.
Can we use the <progress> element instead?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In most cases I would absolutely agree. However, styling the progress element is a little nasty between browsers. It would require a bit more CSS than this PR adds already.

Maybe we could compromise with a few additional aria attributes?

bar.style.transform = `scaleX(${stats.progress})`;

const text = document.querySelector(".progress-text");
text.innerText = `${humanReadable(stats.loaded)} / ${humanReadable(stats.total)}`;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: I think the progress indicator is a bit busy right now. Not yet sure what I would prefer, maybe just the loaded size or a percentage? Even though the percentage is kinda redundant because of the progress bar.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here's a few variations:

Screenshot 2026-02-21 at 2 18 16 PM Screenshot 2026-02-21 at 2 24 16 PM Screenshot 2026-02-21 at 2 30 02 PM Screenshot 2026-02-21 at 2 30 28 PM

We could even go the unity route with a Bevy logo (unless there are any sort of trademark concerns):

Screenshot 2026-02-21 at 2 35 44 PM

Though I do appreciate having the bytes downloaded text over merely a bar.

@ChristopherBiscardi
Copy link
Contributor

I talked with @CorvusPrudens about this in discord offtopic and the conclusion we came to is that the data here seems to not indicate a useful raw MB size display. There was talk of it being used to inform users on metered or slow network connections, but the mb size here is pre-determined and is notably not the wire size, so can not be used to reliably inform a user's network-connection related decisions.

So while the mb data can produce a correct and useful percentage, it can not be actioned by a user who would read the raw mb counts (and it is unclear exactly which mb the count refers to in the current display). As a result: I would suggest using only the percentage for the loading text and removing the raw mb counts.

Including the percentage, however, could increase the legibility of the download progress by allowing users to read the percentage rather than estimate the progress fill percentage.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants