Search code examples
javascriptreactjsemacswebpackwebpack-hmr

Webpack HMR vs Skewer mode in emacs


I have recently started looking into webpack, because of cool features that enable writing true CSS modules, and smart bundling and stuff, and there is HMR, thats why I am here. I have seen examples of React Redux projects that made it possible to update javascript code without reloading browser. WOW, I thought it is impossible.

I wanted to know more, especially how it works under the hood, to make it work with my current project which is Vanilla JS.

In the mean time, my interest in functional programming languages brought me to Emacs. I have found out that there is a skewer-mode available in emacs editor that do update javascript and HTML! in real-time without realoding browser.

I know that they both use local server to push the changes to the browser and some script on client that somehow updates the code. But how do they preserve the state of application. In terms of React projects its kind of imaginable, because of component based nature of apps, you can just replace component with new one, but I am not sure how do they search for variables and reassign new values to them. Maybe they do use some eval magic. But I am not sure.

  1. So how do they exactly work? Maybe I am looking from the wrong angle, I just don't have a clear picture.

  2. Emacs has live update of HTML too, can webpack HMR do that?
    (I don't care much about HTML because I do it in JS. But I think it can explain difference between these two.)

  3. Which is better in doing so?
    What is the pros and cons of each or are they just different parts of the world and can be integrated to become something even better?

  4. Maybe there is a even better options without the need of middleware like local webserver, but just editor plugin communicating with some browser extension?

P.S.: I don't mind learning tools that can optimize my work, because it always pays off.


Solution

  • So how do they exactly work?

    From the Webpack HMR documentation,

    In general the module developer writes handlers that are called when a dependency of this module is updated. He can also write a handler that are called when this module is updated.

    Each module type needs update logic written for it.

    From the skewer-mode repository,

    Expressions are sent on-the-fly from an editing buffer to be evaluated in the browser, just like Emacs does with an inferior Lisp process in Lisp modes.

    Your code is sent to the browser as a string, and runs through a global eval.

    Which is better in doing so? What is the pros and cons of each?

    If you use libraries that have HMR plugins written for them, it might be worth using this feature. Libraries without HMR hooks will not benefit from it. Webpack's HMR seems extremely complex, and its documentation and its plugins warn about HMR's "experimental" state. Therefore, it is probably not reliable, and thus could be counter-productive to your development. For instance, the reloading modules need to correctly clean up the non-reloading ones. What if some script adds listeners to window or document and doesn't provide a way to remove them?

    If you want your text editor to serve as an additional REPL for your browser, then you can use skewer-mode. To effect any change in your application, some part of it must be exposed via a global variable. Maybe you export one global object with a bunch of submodules attached to it, e.g. window.APP = {}, APP.Dialog, APP.Form... or, maybe you just release hundreds of implicit global variables and functions into your environment. You can see changes in your application by evaluating the definitions of these modules / functions / variables, and then evaluating some code that uses them, e.g. by calling a function APP.initialize() which bootstraps your app, or by triggering a redraw in a view library you use (usually by performing a user action like clicking an element).

    If your application is not written such that it can be modified in a browser console (e.g. if you use a module compiler like Browserify or Webpack, which wraps your code in one big closure), then you won't be able to do much with skewer-mode. Also, consider whether it would be faster to manually eval code snippets / files and re-run initialization code (and potentially create impossible application state that you will waste time debugging), or to just refresh the page and recreate your previous state.

    The benefit you gain from either of these tools is heavily reliant on the way your application is structured. I can see them creating pleasant development workflows under exactly the right conditions (what I describe above). Otherwise, they seem too likely to cause harm to be worthwhile.