webpack-hot-middleware icon indicating copy to clipboard operation
webpack-hot-middleware copied to clipboard

Idea: double-save to refresh browser

Open ericclemmons opened this issue 9 years ago • 8 comments

tldr; Save a file once, everything's normal. Save a file twice (like a double-tap), browser refreshes.

Scenario

_Web app that shows how much of a product is left in stock.

  1. I'm viewing a product page: 1 left in stock.
  2. I add it to my cart.
  3. Open a separate window, viewing that same product, I still see 1 left in stock, even though it's in Step 1's cart.
  4. I realize there's a bug in my API from showing the correct total.
  5. I fix the bug in the API, save the code, HMR reloads the server-code. The browser still isn't in sync, though without a refresh.
  6. I save the code again, webpack doesn't build anything (no changes), but the browser HMR sends a reload event and I correctly see 0 left in stock.

I'm asking here because webpack-hot-middleware is what's triggering reload events in the browser and seems like a likely place to be able to trigger the event.

Cool DX, but doable? I'd be happy to help if you can help me figure out where to even do this.

ericclemmons avatar Jul 25 '16 21:07 ericclemmons

Interesting idea, it's possibly doable - depending on what the granularity of the file change event is after a save.

At the moment I just let webpack watch the filesystem, so we would need to reach into webpack and grab the watchpack instance somehow - then compare timestamps of change events.

Another similar option might be to have the middleware expose an HTTP endpoint which sends a force-reload message, and then have editor plugins ping that endpoint on a custom keybinding.

glenjamin avatar Jul 25 '16 22:07 glenjamin

@glenjamin Makes sense to me. I've finagled with Webpack a bit, so if I can work it out would you be open to a PR?

(If it doesn't fit within this project, it can likely be a plugin instead).

ericclemmons avatar Jul 28 '16 03:07 ericclemmons

I'm happy to take a PR, possibly behind an option that's off by default initially.

glenjamin avatar Jul 28 '16 06:07 glenjamin

@glenjamin I <3 you. I'll see what I can do :)

ericclemmons avatar Jul 28 '16 18:07 ericclemmons

@matthiasak Pinging you since this came from our discussion!

ericclemmons avatar Jul 28 '16 18:07 ericclemmons

@ericclemmons @glenjamin

I don't have a ton of experience with the lower internals of webpack or webpack-hot-middleware, but I imagine you'll need to keep track of file hashes for the server-side code separately from the client-side.

In https://github.com/matthiasak/universal-js-boilerplate-v3 I have two configs generated by my webpack.config.js. I use webpack-hot-middleware (WHM) to manage the client-side - and the webpack --watch CLI command to manage the server code. Thus, If I want WHM to track changes in the server-side code, I'd need an option kinda like serverEntry to track those changes and check subsequent file hashes against the prior version.

app.use(require("webpack-hot-middleware")(compiler, {
    serverEntry: ['/path/to/server-entry-file.js']
}))

But this might have some extra overhead in-terms of watching the server files from both the WHM and webpack --watch. Perhaps WHM can take an optional pointer to another webpack instance to hook into its changes?

let serverBundler = webpack(serverConfig)

app.use(require("webpack-hot-middleware")(compiler, {serverBundler}))

matthiasak avatar Jul 29 '16 15:07 matthiasak

WHM can't really do anything useful with a server bundle.

There would be 2 parts to an implementation of the feature suggested here:

  1. Hook into webpack/watchpack events to figure out when the reload-condition is met
  2. Send a message down to the connected clients to force a reload

If you also wanted to force a refresh after server-side changes then that would hopefully only need (1) to be hooked up to the server bundle, and an appropriate method called on the middleware instance.

glenjamin avatar Jul 29 '16 16:07 glenjamin

I figured it made the most sense to solve it in two steps:

  • [ ] Double-save to force reload for client-side bundles.
  • [ ] Double-save to refresh browser when server bundle is saved.

As noted, they'll require 2 different solutions.

ericclemmons avatar Jul 29 '16 19:07 ericclemmons