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

Inject script to auto-reload browser when Rocket restarts #2728

Open
2 tasks done
rikhuijzer opened this issue Feb 16, 2024 · 1 comment
Open
2 tasks done

Inject script to auto-reload browser when Rocket restarts #2728

rikhuijzer opened this issue Feb 16, 2024 · 1 comment
Labels
request Request for new functionality

Comments

@rikhuijzer
Copy link

What's missing?

First of all, thanks for making Rocket. I like it a lot.

I would like to open a feature request. Whenever I change my templates or Rocket code, Rocket restarts automatically with

cargo watch -x run

as described in #292 (comment). However, my browser doesn't automatically refresh the page meaning that I manually have to refresh it upon each change.

Ideal Solution

The ideal solution would be something like what is used in the npm live-server package. There, some Javascript is injected which connects to an open socket. Whenever the server reloads some files, the browser receives a notification and reloads the page.

Why can't this be implemented outside of Rocket?

I wouldn't know how to implement this outside of Rocket.

Are there workarounds usable today?

Yes. One workaround that works reasonably well for me is to inject the following Javascript into my HTML pages when in development mode:

<script>
  function check_reload() {
      fetch("/check_reload").then(response => response.text()).then(data => {
          if (data === "true") {
              location.reload();
          }
      });
  }
  setInterval(check_reload, 2000);
</script>

and to add the following endpoint to my Rocket server:

lazy_static! {
    static ref SHOULD_RELOAD: Mutex<bool> = Mutex::new(true);
}

#[get("/check_reload")]
async fn check_reload() -> String {
    let mut should_reload = SHOULD_RELOAD.lock().unwrap();
    if *should_reload {
        *should_reload = false;
        return "true".to_string();
    } else {
        return "false".to_string();
    }
}

So, what happens here is that the browser asks Rocket ever 2 seconds whether the browser should reload. If Rocket just reloaded, the answer is true. If Rocket has been asked this before but didn't restart, then the answer is false.

There are some drawbacks to this approach though:

  1. I have to set log_level = "critical" in Rocket.toml to avoid seeing one request pop up every 2 seconds (this would not happen with a socket).
  2. The browser "network" inspection tools are full of requests (this would not happen with a socket).
  3. There is a delay of 2 seconds before the page reloads (or even more requests spamming the logs).
  4. I'm not using templates currently, but I think my logic will not work correctly there.

Alternative Solutions

Ideally, something would wrap around Rocket which keeps track of changes and keeps a socket open. Whenever Rocket then changes, it would notify the browser. I guess this could be something like nginx but then with some logic to track whether Rocket changed.

Additional Context

No response

System Checks

  • I do not believe that this feature can or should be implemented outside of Rocket.
  • I was unable to find a previous request for this feature.
@rikhuijzer rikhuijzer added the request Request for new functionality label Feb 16, 2024
@the10thWiz
Copy link
Collaborator

This is more difficult than you might think. I'm not sure how npm's live-server works, but I suspect it's unloading and reloading the server, but keeping any existing steaming connections alive. For Rocket, because we aren't an interpreted language, when Rocket is restarted, the OS automatically resets every connection, so sockets would be disconnected in this case.

I think this could be implemented outside of Rocket, but it would require forking cargo watch to make it work. The idea is that it would open a Websocket Server on a different port (say 8001), and the client script would force reload the page when asked by the server. Injecting the client script automatically likely isn't worth the effort, especially since we don't know what each page is used for. I would suggest simply asking the users to inject it by hand, but a more automated solution might be possible via the webdriver spec.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
request Request for new functionality
Projects
None yet
Development

No branches or pull requests

2 participants