Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Explore asset hot reloading for bevy run web #189

Open
TimJentzsch opened this issue Dec 3, 2024 · 0 comments
Open

Explore asset hot reloading for bevy run web #189

TimJentzsch opened this issue Dec 3, 2024 · 0 comments
Labels
A-Run Related to the bevy run command A-Web Building or running Bevy apps targeting the browser C-Feature Make something new possible D-Complex Quite challenging from either a design or technical perspective. Ask for help! S-Needs-Design This issue requires design work to think about how it would best be accomplished

Comments

@TimJentzsch
Copy link
Collaborator

TimJentzsch commented Dec 3, 2024

Asset hot reloading is a very important feature of Bevy.
Due to Rust's relatively slow compile times, it can really improve the speed of the development cycle.

Unfortunately, it's not available when targeting the browser.
The main reason is that web apps don't have direct access to the file system and we cannot assume a specific web server implementation, so no standard API to communicate file changes between the server and web client.

With the Bevy CLI, we have full control over the development web server!
So it's likely possible that we can make hot reloading work.

Requirements

  • Simple: Hot-reloading should work without additional configuration, or (if impossible) with very simple adjustments (e.g. adding one additional plugin to their app). They shouldn't have to make fundamental changes to their app.
  • Optional: If the user would have to make changes to their app in order to get hot reloading, they don't have to! Everything else should still work without adjustments. If we can make hot reloading work by default, the user should probably have a way to opt out.

Potential solutions

The Bevy CLI would create file watchers for the asset directory and then somehow communicate the changes to the Bevy app.
I can see two ways of communication:

  1. Client-authoritive: The Bevy app regularly makes API calls to the server, asking which changes happened since the last call.
  2. Server-authoritive: Whenever a change happens, the server directly sends them over to the client (perhaps using web-sockets?).

Afterwards, the Bevy app has to process these events, likely forwarding them to the asset server / asset source. This source then performs the reload, same as for native hot-reloading.
Triggering the internal hot-reload likely requires changes to Bevy itself, so we can access the relevant functionality from "outside".

@TimJentzsch TimJentzsch added C-Feature Make something new possible A-Build Related to the bevy build command A-Web Building or running Bevy apps targeting the browser D-Complex Quite challenging from either a design or technical perspective. Ask for help! labels Dec 3, 2024
@TimJentzsch TimJentzsch added A-Run Related to the bevy run command and removed A-Build Related to the bevy build command labels Jan 5, 2025
@TimJentzsch TimJentzsch added the S-Needs-Design This issue requires design work to think about how it would best be accomplished label Jan 13, 2025
TimJentzsch added a commit that referenced this issue Feb 3, 2025
# Objective

Closes #234.

If you terminate `cargo run` and then run it again, your old application
will have closed and a new one with the newest state opens.

With `bevy run web`, if you terminate the command, only the dev server
terminates, the application will keep running.
If you re-run the command, the tab in the browser will still contain
your old code.

Instead, we want the page to refresh to ensure that the page is
up-to-date.

# Solution

The solution here is adopted from (an old version of) Trunk's auto
reloading, see <trunk-rs/trunk#231>.

The basic idea is that we inject a script into the `index.html` to open
a websocket to the dev server.
When the websocket connection closes (i.e., the server has been shut
down), we periodically try to reconnect again and trigger a reload when
that happens.

Actually, before trying to connect the websocket, we first send a `PING`
request to the same URL. This prevents us spamming the console with
errors due to the websocket connection failing, I couldn't find a good
way to suppress them.

Note that the autoreload script is currently just injected when not in
bundling mode and if the user didn't specify a custom `index.html`.
This is because we really only want to inject this in the dev version,
not in any deployed version.
I plan to lift this limitation in a future PR, but it will require a bit
of restructuring and I didn't want to blow this up more than necessary.

# Testing

With the Bevy CLI installed from this branch:

1. On any Bevy project, use `bevy run web --open`.
2. Wait for the build to complete and the app to load in the browser.
3. (If you want, perform small changes to the code).
4. Shut down the server by terminating the command.
5. Run `bevy run web`.
6. Once the build has completed, the browser tab with your app should
automatically refresh!

# Future Work

- Expand auto reload support to bundled mode and for custom
`index.html`.
- Having a websocket connection between the client and server means that
we are able to send messages from the server to the client (once I
figure out how exactly to do that). This opens up a vast array of
possibilities. With the `reload` message that's already supported with
the current client implementation, we could implement a `bevy watch`
(#245). We could also add cold and eventually hot reloading on asset
changes (#189). We could also display build errors directly in the
browser window, which I believe the current Trunk version is doing.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-Run Related to the bevy run command A-Web Building or running Bevy apps targeting the browser C-Feature Make something new possible D-Complex Quite challenging from either a design or technical perspective. Ask for help! S-Needs-Design This issue requires design work to think about how it would best be accomplished
Projects
None yet
Development

No branches or pull requests

1 participant