阿里云主机折上折
  • 微信号
Current Site:Index > Implementation of hot module replacement

Implementation of hot module replacement

Author:Chuan Chen 阅读数:46376人阅读 分类: Vue.js

Implementation of Hot Module Replacement

Hot Module Replacement (HMR) is a core feature of modern front-end development toolchains, allowing applications to replace, add, or delete modules at runtime without a full page refresh. Vue 3 deeply integrates HMR through tools like @vue/compiler-sfc and vite, enabling developers to enjoy this feature with minimal additional configuration.

Basic Principles of HMR

The core of HMR lies in establishing a dependency graph between modules. When a file is modified, the toolchain locates the affected modules and pushes the changes to the client via WebSocket. Upon receiving the changes, the client runtime executes the module replacement logic. For example:

// Pseudocode illustrating the core HMR flow
if (import.meta.hot) {
  import.meta.hot.accept('./moduleA.js', (newModule) => {
    // Callback after the new module is loaded
    console.log('Module updated:', newModule)
  })
}

HMR Implementation Mechanism in Vue 3

Vue Single File Components (SFCs) require special handling for HMR because they consist of templates, scripts, and styles. @vue/compiler-sfc compiles SFCs into JavaScript code with HMR markers:

// Compiled component code snippet
import { createHotContext } from "vite/hmr"
const __VUE_HMR_RUNTIME__ = createHotContext("/src/App.vue")

__VUE_HMR_RUNTIME__.createRecord('7ba5bd90', Component)
__VUE_HMR_RUNTIME__.reload('7ba5bd90', Component)

Optimization Strategy for Template Updates

Vue 3 employs special optimizations for template updates. When a template change is detected, it executes the following steps:

  1. Destroy the current component instance
  2. Recreate a new VNode tree
  3. Compare differences using the patch algorithm
  4. Minimize DOM operations

Example demonstrating HMR triggering for template modifications:

<!-- Before modification -->
<template>
  <div>{{ count }}</div>
</template>

<!-- After modification -->
<template>
  <div class="counter">{{ count }} times</div>
</template>

Implementation of State Preservation

Vue 3 preserves component state using the __VUE_HMR_RUNTIME__.rerender method, which:

  1. Creates a new component instance
  2. Transfers the state from the old instance to the new one
  3. Triggers reactive system updates

Key code for state transfer:

function cloneState(original) {
  if (typeof original === 'object' && original !== null) {
    return reactive(original)
  }
  return original
}

Special Handling for Style Hot Updates

Style hot updates are divided into two scenarios:

  1. <style> block modifications: Directly replace the style element
  2. <style module> modifications: Regenerate CSS module class names

Example of style HMR markers:

import { updateStyle } from "vite/client"
const __injectCSS = (css, id) => updateStyle(id, css)
__injectCSS("body{color:red}", "123456")

Custom HMR Handling Logic

Developers can customize handling logic using hot.accept. A typical use case is store hot updates:

// store.js
export const store = reactive({ count: 0 })

if (import.meta.hot) {
  import.meta.hot.accept((newModule) => {
    // Merge state
    Object.assign(store, newModule.store)
  })
}

Error Recovery Mechanism

When HMR updates fail, Vue 3 implements a fallback strategy:

  1. Attempt component-level hot updates
  2. Fall back to parent component updates if unsuccessful
  3. Ultimately revert to a full page refresh

Example of error handling:

import.meta.hot.on('vite:beforeUpdate', () => {
  // Preprocessing logic
})

import.meta.hot.on('vite:error', (err) => {
  // Error handling
})

Performance Optimization Techniques

Vue 3's HMR incorporates several performance optimizations:

  1. Lazy loading of changed modules
  2. Update batching
  3. Dependency tree pruning

Key performance path code:

const queue = new Set()
let isFlushing = false
function queueUpdate(component) {
  queue.add(component)
  if (!isFlushing) {
    isFlushing = true
    Promise.resolve().then(flushUpdates)
  }
}

Deep Integration with Build Tools

Vite achieves faster HMR updates through native ESM. Its core workflow:

  1. File system monitors file changes
  2. Sends update events via WebSocket
  3. Browser dynamically requests new modules

Example of Vite's HMR protocol:

{
  "type": "update",
  "updates": [
    {
      "type": "js-update",
      "path": "/src/main.js",
      "acceptedPath": "/src/main.js"
    }
  ]
}

HMR Handling for Server-Side Rendering

SSR environments require special HMR handling:

  1. Client and server maintain separate module graphs
  2. Bidirectional HMR event communication
  3. Serialized state synchronization

Example SSR HMR configuration:

// vite.config.js
export default {
  server: {
    hmr: {
      protocol: 'ws',
      host: 'localhost',
      port: 3000,
      overlay: false
    }
  }
}

Boundary Condition Handling in HMR

Vue 3 addresses various edge cases:

  1. Dynamic component updates
  2. Async component loading
  3. KeepAlive component state preservation

Example of dynamic component HMR:

<script setup>
const componentMap = {
  A: defineAsyncComponent(() => import('./CompA.vue')),
  B: defineAsyncComponent(() => import('./CompB.vue'))
}
</script>

Hot Update Lifecycle Hooks

Vue components can listen to their own HMR events:

export default {
  created() {
    const unwatch = this.$watch(
      () => this.$options.__hmrId,
      () => {
        // Custom logic during component hot updates
      }
    )
  }
}

Atomicity Guarantee for Module Replacement

Vue 3 ensures atomicity in HMR updates:

  1. Synchronous updates for all dependencies
  2. Batched DOM updates
  3. Transactional state migration

Example of atomic update code:

function applyUpdate(module) {
  performPreUpdateTasks()
  try {
    commitUpdate(module)
  } catch (e) {
    rollbackUpdate()
  }
  performPostUpdateTasks()
}

本站部分内容来自互联网,一切版权均归源网站或源作者所有。

如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn

Front End Chuan

Front End Chuan, Chen Chuan's Code Teahouse 🍵, specializing in exorcising all kinds of stubborn bugs 💻. Daily serving baldness-warning-level development insights 🛠️, with a bonus of one-liners that'll make you laugh for ten years 🐟. Occasionally drops pixel-perfect romance brewed in a coffee cup ☕.