vitejs.dev Open in urlscan Pro
3.78.41.232  Public Scan

URL: https://vitejs.dev/guide/api-hmr
Submission: On December 29 via api from US — Scanned from DE

Form analysis 0 forms found in the DOM

Text Content

Skip to content
Vite
SearchK
Main NavigationGuideConfigPlugins
Resources
Team
Blog
Releases
Twitter
Discord Chat
Awesome Vite
ViteConf
DEV Community
Rollup Plugins Compat
Changelog
Contributing
Version
Vite 4 Docs
Vite 3 Docs
Vite 2 Docs

English

简体中文
日本語
Español
Português
한국어
Deutsch

MastodonTwitterDiscordGitHub

English

简体中文
日本語
Español
Português
한국어
Deutsch

Appearance


MastodonTwitterDiscordGitHub
Menu
On this page
Sidebar Navigation


GUIDE

Why Vite

Getting Started

Features

CLI

Using Plugins

Dependency Pre-Bundling

Static Asset Handling

Building for Production

Deploying a Static Site

Env Variables and Modes

Server-Side Rendering (SSR)

Backend Integration

Comparisons

Troubleshooting

Performance

Philosophy

Migration from v4


APIS

Plugin API

HMR API

JavaScript API

Config Reference

On this page
Table of Contents for current page
   
 * Required Conditional Guard
 * IntelliSense for TypeScript
 * hot.accept(cb)
 * hot.accept(deps, cb)
 * hot.dispose(cb)
 * hot.prune(cb)
 * hot.data
 * hot.decline()
 * hot.invalidate(message?: string)
 * hot.on(event, cb)
 * hot.off(event, cb)
 * hot.send(event, data)
   



Beyond Fast

ViteConf 2023

Watch the replay!

STACKBLITZ

NUXTLABS

ASTRO

STORYBLOK

BIT

REMIX

TAILWIND LABS

VUE JOBS

DIVRIOTS

PREFECT.IO

JETBRAINS

MUX


Dedicated Server für kleine und mittlere Projekte zum kleinen Preis. ads via
Carbon

On this page


HMR API

Note

This is the client HMR API. For handling HMR update in plugins, see
handleHotUpdate.

The manual HMR API is primarily intended for framework and tooling authors. As
an end user, HMR is likely already handled for you in the framework specific
starter templates.

Vite exposes its manual HMR API via the special import.meta.hot object:

ts

interface ImportMeta {
  readonly hot?: ViteHotContext
}

type ModuleNamespace = Record<string, any> & {
  [Symbol.toStringTag]: 'Module'
}

interface ViteHotContext {
  readonly data: any

  accept(): void
  accept(cb: (mod: ModuleNamespace | undefined) => void): void
  accept(dep: string, cb: (mod: ModuleNamespace | undefined) => void): void
  accept(
    deps: readonly string[],
    cb: (mods: Array<ModuleNamespace | undefined>) => void,
  ): void

  dispose(cb: (data: any) => void): void
  prune(cb: (data: any) => void): void
  invalidate(message?: string): void

  // `InferCustomEventPayload` provides types for built-in Vite events
  on<T extends string>(
    event: T,
    cb: (payload: InferCustomEventPayload<T>) => void,
  ): void
  off<T extends string>(
    event: T,
    cb: (payload: InferCustomEventPayload<T>) => void,
  ): void
  send<T extends string>(event: T, data?: InferCustomEventPayload<T>): void
}


REQUIRED CONDITIONAL GUARD

First of all, make sure to guard all HMR API usage with a conditional block so
that the code can be tree-shaken in production:

js

if (import.meta.hot) {
  // HMR code
}


INTELLISENSE FOR TYPESCRIPT

Vite provides type definitions for import.meta.hot in vite/client.d.ts. You can
create an env.d.ts in the src directory so TypeScript picks up the type
definitions:

ts

/// <reference types="vite/client" />


HOT.ACCEPT(CB)

For a module to self-accept, use import.meta.hot.accept with a callback which
receives the updated module:

js

export const count = 1

if (import.meta.hot) {
  import.meta.hot.accept((newModule) => {
    if (newModule) {
      // newModule is undefined when SyntaxError happened
      console.log('updated: count is now ', newModule.count)
    }
  })
}

A module that "accepts" hot updates is considered an HMR boundary.

Vite's HMR does not actually swap the originally imported module: if an HMR
boundary module re-exports imports from a dep, then it is responsible for
updating those re-exports (and these exports must be using let). In addition,
importers up the chain from the boundary module will not be notified of the
change. This simplified HMR implementation is sufficient for most dev use cases,
while allowing us to skip the expensive work of generating proxy modules.

Vite requires that the call to this function appears as import.meta.hot.accept(
(whitespace-sensitive) in the source code in order for the module to accept
update. This is a requirement of the static analysis that Vite does to enable
HMR support for a module.


HOT.ACCEPT(DEPS, CB)

A module can also accept updates from direct dependencies without reloading
itself:

js

import { foo } from './foo.js'

foo()

if (import.meta.hot) {
  import.meta.hot.accept('./foo.js', (newFoo) => {
    // the callback receives the updated './foo.js' module
    newFoo?.foo()
  })

  // Can also accept an array of dep modules:
  import.meta.hot.accept(
    ['./foo.js', './bar.js'],
    ([newFooModule, newBarModule]) => {
      // The callback receives an array where only the updated module is
      // non null. If the update was not successful (syntax error for ex.),
      // the array is empty
    },
  )
}


HOT.DISPOSE(CB)

A self-accepting module or a module that expects to be accepted by others can
use hot.dispose to clean-up any persistent side effects created by its updated
copy:

js

function setupSideEffect() {}

setupSideEffect()

if (import.meta.hot) {
  import.meta.hot.dispose((data) => {
    // cleanup side effect
  })
}


HOT.PRUNE(CB)

Register a callback that will call when the module is no longer imported on the
page. Compared to hot.dispose, this can be used if the source code cleans up
side-effects by itself on updates and you only need to clean-up when it's
removed from the page. Vite currently uses this for .css imports.

js

function setupOrReuseSideEffect() {}

setupOrReuseSideEffect()

if (import.meta.hot) {
  import.meta.hot.prune((data) => {
    // cleanup side effect
  })
}


HOT.DATA

The import.meta.hot.data object is persisted across different instances of the
same updated module. It can be used to pass on information from a previous
version of the module to the next one.

Note that re-assignment of data itself is not supported. Instead, you should
mutate properties of the data object so information added from other handlers
are preserved.

js

// ok
import.meta.hot.data.someValue = 'hello'

// not supported
import.meta.hot.data = { someValue: 'hello' }


HOT.DECLINE()

This is currently a noop and is there for backward compatibility. This could
change in the future if there is a new usage for it. To indicate that the module
is not hot-updatable, use hot.invalidate().


HOT.INVALIDATE(MESSAGE?: STRING)

A self-accepting module may realize during runtime that it can't handle a HMR
update, and so the update needs to be forcefully propagated to importers. By
calling import.meta.hot.invalidate(), the HMR server will invalidate the
importers of the caller, as if the caller wasn't self-accepting. This will log a
message both in the browser console and in the terminal. You can pass a message
to give some context on why the invalidation happened.

Note that you should always call import.meta.hot.accept even if you plan to call
invalidate immediately afterwards, or else the HMR client won't listen for
future changes to the self-accepting module. To communicate your intent clearly,
we recommend calling invalidate within the accept callback like so:

js

import.meta.hot.accept((module) => {
  // You may use the new module instance to decide whether to invalidate.
  if (cannotHandleUpdate(module)) {
    import.meta.hot.invalidate()
  }
})


HOT.ON(EVENT, CB)

Listen to an HMR event.

The following HMR events are dispatched by Vite automatically:

 * 'vite:beforeUpdate' when an update is about to be applied (e.g. a module will
   be replaced)
 * 'vite:afterUpdate' when an update has just been applied (e.g. a module has
   been replaced)
 * 'vite:beforeFullReload' when a full reload is about to occur
 * 'vite:beforePrune' when modules that are no longer needed are about to be
   pruned
 * 'vite:invalidate' when a module is invalidated with
   import.meta.hot.invalidate()
 * 'vite:error' when an error occurs (e.g. syntax error)
 * 'vite:ws:disconnect' when the WebSocket connection is lost
 * 'vite:ws:connect' when the WebSocket connection is (re-)established

Custom HMR events can also be sent from plugins. See handleHotUpdate for more
details.


HOT.OFF(EVENT, CB)

Remove callback from the event listeners


HOT.SEND(EVENT, DATA)

Send custom events back to Vite's dev server.

If called before connected, the data will be buffered and sent once the
connection is established.

See Client-server Communication for more details.

Suggest changes to this page
Previous pagePlugin API
Next pageJavaScript API

Released under the MIT License. (a1c9221a)

Copyright © 2019-present Evan You & Vite Contributors