Hot Module Replacement is Easy

This ad is not shown to multipass and full ticket holders
React Summit US
React Summit US 2025
November 18 - 21, 2025
New York, US & Online
The biggest React conference in the US
Learn More
In partnership with Focus Reactive
Upcoming event
React Summit US 2025
React Summit US 2025
November 18 - 21, 2025. New York, US & Online
Learn more
Bookmark
Rate this content

Learn how Vite's Hot Module Replacement (HMR) works under the hood and all the key concepts that power it.

This talk has been presented at JSNation 2025, check out the latest edition of this JavaScript Conference.

FAQ

Tools like Vite, Parcel, and Webpack have built-in support for homework replacement, allowing developers to update code more efficiently.

HTML APIs in homework replacement act as hooks in the lifecycle, allowing you to accept changes, dispose of unneeded states, prune removed modules, and invalidate when changes are not as expected.

When a module accepts HMR, the hooks implemented for that module are executed, and any new modules are updated within the accepted boundary.

The server watches for file changes, triggers invalidation and propagation, and informs the client whether modules need to be updated or if a full page reload is required.

The client sets up HTML APIs to receive instructions from the server. It updates the necessary modules or performs a full reload based on the server's instructions.

HMR allows developers to see changes in real-time without refreshing the page, speeding up the development process by allowing faster iteration and testing.

For more in-depth details on HMR implementation in Vite, you can visit Vite's Discourse or follow discussions on platforms like BlueSky or X.

A full page reload is required if no modules can accept changes or if there are interconnected modules where not all can accept changes.

Homework replacement, also known as Hot Module Replacement (HMR), allows you to update your code without having to refresh your page. It enables immediate viewing of changes in your browser when updating components or adjusting styles.

Bjorn Lu
Bjorn Lu
11 min
16 Jun, 2025

Comments

Sign in or register to post your comment.
Video Summary and Transcription
Welcome to JS Nation. Homework replacement, also known as HTML, allows code updates without page refresh. Understanding HTML involves APIs, server reactions to file edits, and client-side handling of changes. HTML API lifecycle includes attaching callbacks, disposing unneeded states, and accepting new modules. Server handling file changes, finding related modules, and HTML propagation decisions determine module execution and page reload. Propagation scenarios dictate HTML updates within boundaries or full reloads. Client-server communication through WebSocket manages reloads or module updates.
Available in Español: Hot Module Replacement es Fácil

1. Homework Replacement Overview

Short description:

Welcome to JS Nation. Homework replacement, also known as HTML, allows code updates without page refresh. Tools like Vite, Parcel, Webpack have it built-in. Understanding HTML involves APIs, server reactions to file edits, and client-side handling of changes.

Hello. Welcome to JS Nation. I'm Bjorn. I want to talk about homework replacement today. So homework replacement is a big topic. Hopefully, this talk will make it more easy to understand for you and more digestible.

So let's jump right into it. What is homework replacement? Homework replacement is also known as HTML. It allows you to update your code without having to refresh your page. So when you update your components or adjust your styles, you can immediately see the changes in your browser. It allows you to iterate much faster than having to wait for the bundle to finish.

So if you have used tools like Vite, Parcel, Webpack, for example, in this right-side here, this Vite logo, and also on my shirt here, this Vite logo, it's where I'm a co-team of. So they have homework replacement built in. So if you have used them, you likely have already experienced something like this in practice. So let's jump to how it really works inside them. So there are different ways to understand HTML. It's quite a big system.

So there's kind of three things that we can look into from the point of view. There are HTML APIs, where you implement how the module replacement is actually done. There is the flow from the server, so when you edit the file, how the server reacts to it. There's also the flow from the client, so the browser will try to handle changes from the server. These three things we're going to cover next. So HTML APIs, you can think of it as hooks. In the HTML lifecycle, sometimes you would have to accept changes when a new module comes in. So this hook tells you that you can accept changes. You can do the replacement. So you'd attach a callback so that you do the necessary changes there. There's a disposal if you need to dispose any unneeded states.

2. HTML API Lifecycle Details

Short description:

You'd attach a callback for necessary changes. Dispose unneeded states, prune removed modules, and invalidate unexpected changes. Lifecycle involves disposing, accepting for replacement, updating, and pruning modules. Accept new modules, handle imported changes, and mutate states using hooks.

So you'd attach a callback so that you do the necessary changes there. There's a disposal if you need to dispose any unneeded states. For example, you have a state there is no longer use before the updates, you do it there. There's a prune if you have a module that's removed. For example, if you remove an import, and you don't need it, you can remove the state completely. And there's also invalidate. This is less a hook, but more like a like an action. But we touch on it later, where if you have the changes suddenly not going as expected, you can call this to restart the loop HTML again. So you can look at the graph on the right side, you can see that when you have a file, you can set up the HTML callbacks here. So you can use the hooks around here with these APIs. And then whenever update the file, you call dispose, and then you call accept to do the replacement, and then we update again and perform the same thing again. And then we delete the file, you dispose, and then finally you call prune. So this is more or less the lifecycle for each modules.

So accept, you can have two signatures, if you're using practice, you can accept the current module. So a new module comes in you accept it and the replacement. You can also accept changes from the imported modules. Maybe this is what you care about, you can do the changes there. And then you mutate any state that you want. And this hook usually just handle a vplugin, so if you install a react-vue-svelte-vplugin, this is basically what they're doing under the hook. It's a bit more isolated because components are more isolated in Vue-Svelte components. So the changes are more idiomatic than what's shown here, but roughly they're using this hook to do the changes that they need to. And this is the most important part of the HTML API to think about for accepting. There's also dispose and prune.

Here's an example. You can use dispose to reset a global state if you're not using it. You can also delete the state if the module is not used at all. So this is some ways that you can also use the hook callbacks and there's also invalid. So in this example here, you try to accept callback, but something strange is not working. So you're gonna bail out, and then invalidate. So this is just one use case, you can use invalidate for.

3. Server File Changes and HTML Propagation

Short description:

Server handling file changes, finding related modules, and updating recursively. HTML propagation decides module execution and page reload. HTML updates occur within components and create artificial HTML boundaries.

So let's jump right into how the server actually handles the changes when you edit the file. So we can take a look at the graph on the right side as well. When you edit a file, there's FileSystemWatcherDetectChanges, and then there's RenulChanges. And then the next step is to figure out the module shader to a file. So as mentioned here, there's React, Vue, Svelte components. Some of them have JS portion of code, and then they have the CSS version of the code, like the Vue components or Svelte components. So multiple modules could be related to a file. So I try to find the modules right in this step. And then once you have the modules, we pass it to the HandleHotUpdate hook. So this is a Vite plugin hook. Specifically, they can change the array, they can add more modules, they can remove more modules depending on the circumstances. And then after that, we invalidate the module recursively. So if the module ourselves needs to be updated, we need to tell the parent to import the new version of ourselves. And to do that, we have to invalidate the parent so the code that imports the child gets updated. And then the parent, the parent have to do the same thing again so that it gets invalidated recursively. So that's how it happens in this step. So you remove the cache so that next time when it imports it, you will do the retransform over again. And then we have the HTML propagation. So this is the main part of HTML, which is probably the most magical part and the more complex part we touch on in the next slide later. So HTML propagation, we decide if what accepted modules are found. So these modules will execute the HTML hooks that you have implemented earlier, or it will decide if you have to reload the page if there's something unexpected going on. There's no changes that can be accepted. And then lastly, once you figure that out, we relay the HTML kind to do the handling.

So let's jump right into HTML propagation. So let's take a quick look on the right side of the graph. You can see a very simple app where you have a HTML right here, imports on JS code, imports a component after JSX when you think of it as a React component or something else. It accepts HTML. So when you update the component, it can update within itself. And then it also imports on JSR. So in this case, you can think of a circle, HTML boundary that is created artificially when a module accepts HTML.

4. Propagation Scenarios and Module Updates

Short description:

Concept of propagation scenarios: updates requiring HTML acceptance or full reload. Updating within boundaries or resorting to full reload based on acceptance. Complex scenarios determine module updates or full reload necessity. Vendors decide module execution or full page reload requirements.

This is more of a concept that you can try to think of when figuring out how propagation works, but it's not really something that's being enforced in toolings. But let's jump right into some scenarios of how propagation works. So let's say a style or JS gets updated. So we have this one gets updated because when it's updated, it doesn't accept HTML. It needs to look for the parent to see that if anyone could accept HTML. So obviously, when you go upwards right here, you can see that FJSX, it accepts HTML. So we start right here. We found the modules that can accept HTML. So the hooks that we've added for this module, we get executed, and then we get the new modules when it updates. So this is one scenario. Another scenario is when you have main.js updated. So this one, so you can see it's outside of the boundary. And when we go upwards, there's no modules that can accept HTML. So remember that HTML can only happen when the import manner.hot.accept API gets called. So these modules doesn't have by default. So when it reaches the root, there's nothing else to accept, it just resort to a full reload. So in this case, we do a full reload for scenario two. And then another scenario is what if we have the component update directly. In this case, we can figure out that it already accepts HTML by itself. So in this case, it's very similar scenario one, it's inside the boundary in this case. So it updates within itself. So this one gets updated, the rest of the modules in the top will be updated in this case. And then another scenario, let's say this case, which is a bit complex, you have two parents here, one going to JSX file and one going to the JS file. So in this case, you might think that this one would ever accept changes. But we have to also account for the other JS file that doesn't even accept changes. And then when it goes upwards here, to the root, there's no way for it to adapt to the new code from the utils file. So the safest way that we could assume is to do a full reload. So even though there's one that could accept changes, if there's at least one else that doesn't able to accept changes, we have to do a full reload. So these are just some cases where Vite or other vendors try to figure out which modules need to be executed of its HTML API hooks or a full page reload is needed. Let's also jump right next to the client.

5. Client Interaction and Server Communication

Short description:

Passing reload or update information via WebSocket connection. Handling full reload or module updates based on server instructions. Client interaction with server through WebSocket for updates or reloads.

So imagine if we already have the information of whether we should do a full reload, or we should do the updates, we can pass it through a WebSocket connection from the server the client will receive a message right here. It receives a payload, we can parse it. And the server might tell us to do a full reload. In this case, we do a location of reload to reload the page. Or it could return some modules that we need to update. And then we just figure out which modules we have to do the updates and call its HTML APIs for. And to do that, the client also sets up the HTML APIs.

So if you look at the code here, basically this is what it injects under the hood so you wouldn't really see it. But it's not really magical. It injects some code that mutates import meta.hot so that you can call import meta.hot to accept something like this. So this is how it sets up the API. And then there's also the other way of communicating the server. So if you have code that couldn't accept, you call invalidate. Like they hopefully mentioned earlier, if it needs to be invalidated, you just tell the server that it needs to invalidate on this specific path.

So that it does HTML propagation again, to see that if someone else does the module instead, or in the worst case, we need to do a full reload. So these are ways that the client can interact with the server. So a recap of what it talks about so far, we know that HTML APIs can use with hope to de-HTML lifecycle. We can also know that the server watches the file system. It triggers invalidation, the propagation, and informs the client of which modules need to update, or whether it needs a full page reload. And the HTML client sets up the HTML APIs for use, and also to receive instructions from the server, whether we need to do the updates or reloads, and then it does the execute hooks accordingly.

Check out more articles and videos

We constantly think of articles and videos that might spark Git people interest / skill us up or help building a stellar career

Vite: Rethinking Frontend Tooling
JSNation Live 2021JSNation Live 2021
31 min
Vite: Rethinking Frontend Tooling
Top Content
Vite is a next-generation build tool that leverages native ES modules for improved performance. It eliminates the need for bundling and improves hot module replacement. Vite provides an opinionated default configuration while still allowing advanced customization through plugins. It is framework agnostic and can be used for React and other applications. Vite is being adopted by Next.js and Create React App, and integration with Nuxt 3 offers significant speed improvements.
Welcome to Nuxt 3
Vue.js London Live 2021Vue.js London Live 2021
29 min
Welcome to Nuxt 3
Top Content
Nux3 has made significant improvements in performance, output optimization, and serverless support. Nuxt Bridge brings the Nitro engine for enhanced performance and easier transition between Nuxt 2 and Nuxt Read. Nuxt 3 supports Webpack 5, Bytes, and Vue 3. NextLab has developed brand new websites using Docus technology. Nuxt.js is recommended for building apps faster and simpler, and Nuxt 2 should be used before migrating to Nuxt 3 for stability. DOCUS is a new project that combines Nuxt with additional features like content modules and an admin panel.
Vite and the Future of JavaScript Tooling
JSNation 2025JSNation 2025
23 min
Vite and the Future of JavaScript Tooling
Top Content
Evan Yeo discusses Vite's growth, challenges with dependencies like ES Build and Rollup, and the creation of the bundler Rolldown. The JavaScript ecosystem faces fragmentation, but the company aims for a unified JavaScript stack. Rust is chosen for lower-level development, while JavaScript and TypeScript for high-level APIs. Roldown offers advanced bundling features, outperforming existing tools. Integration with Vite leads to tailored optimizations and significant speed improvements. Vite+ development focuses on creating a comprehensive toolkit. VitePlus integrates TS-down for library bundling, ViteTest for testing, and OX-Lint for linting. Future plans include monorepo awareness, build orchestration, and framework-like features.
10 Years of Independent OSS: A Retrospective
JSNation 2024JSNation 2024
33 min
10 Years of Independent OSS: A Retrospective
This talk is a ten-year retrospective into the growth of the Vue.js framework as an open-source project. It highlights the challenges faced by open-source developers, the importance of finding balance and managing scope, and the collaborative nature of the Vue community. The talk also discusses the development of Vite as a build tool and the vision for a unified JavaScript toolchain. It emphasizes the need for community alignment, contributions, and testing, while acknowledging the challenges of bad actors in the open-source community.
What's New in Vite 6
JSNation US 2024JSNation US 2024
29 min
What's New in Vite 6
Watch video: What's New in Vite 6
Vite, a popular build tool for front-end development, has seen significant growth since its public release in 2021. It has been downloaded 12 million times and has over 1,000 contributors. Vite offers benefits such as a powerful dev server, hot module reloading, and a plugin API based on Rollup. However, there are limitations with server-side rendering that require extra code and handling of SSR flags. Vite's environment API allows for cleaner communication between the browser and server, and plugins can configure and customize specific environments. The future plans for Vite include stabilizing the environment API and integrating Rolldown Vite for faster builds. Vite is compatible with various front-end frameworks and is used by projects like Vaku and Vinci. The environment API has potential for per-local builds and building on older versions of Node, but may not be recommended for internationalization purposes.
The Inner Workings of Vite Build
DevOps.js Conf 2022DevOps.js Conf 2022
31 min
The Inner Workings of Vite Build
Welcome to vidBuild, a tool that optimizes your application for production by offering fast hodgemodule replacement and support for various technologies. The build process in vidBuild involves optimizing and minifying assets, bundling JS and CSS, and generating chunks for dynamic imports. The pipeline in vidBuild includes plugins for alias, resolution, CSS modules, and asset handling. Vid is a complete build tool with a flexible plugin system and support from a vibrant community. Vite's plugin API is compatible with Rollup, and Vite aims for simplicity while pushing complexity to the plugin system.