Vite HMR API

前端精髓

共 2390字,需浏览 5分钟

 · 2022-11-09


import.meta 是一个给 JavaScript 模块暴露特定上下文的元数据属性的对象。它包含了这个模块的信息,比如说这个模块的 URL。


<script type="module">  console.log(import.meta)  // {url: 'http://127.0.0.1:5500/dist/index.html?a=1'}</script>


import.meta 对象由一个关键字 "import",一个点符号和一个 meta 属性名组成。通常情况下 "import." 是作为一个属性访问的上下文,但是在这里 "import" 不是一个真正的对象。


import.meta 对象是由 ECMAScript 实现的,它带有一个 null 的原型对象。这个对象可以扩展,并且它的属性都是可写,可配置和可枚举的。


HMR (Hot Module Replacement)

Pinia 支持热更新,所以你可以编辑你的 store,并直接在你的应用中与它们互动,而不需要重新加载页面,允许你保持当前的 state、并添加甚至删除 state、action 和 getter。


目前,只有 Vite 被官方支持,不过任何实现 import.meta.hot 规范的构建工具都应该能正常工作。(例外的是,webpack 似乎使用的是 import.meta.webpackHot 而不是 import.meta.hot ) 你只需要在任何 store 声明旁边添加这段代码。比方说,你有三个 store:auth.js、 cart.js 和 chat.js, 你必须在每个 store 声明后都添加(和调整)这段代码。


// auth.jsimport { defineStore, acceptHMRUpdate } from 'pinia'
const useAuth = defineStore('auth', { // 配置...})
// 确保传递正确的 store 声明,本例中为 `useAuth`if (import.meta.hot) { import.meta.hot.accept(acceptHMRUpdate(useAuth, import.meta.hot))}

Vite HMR API

Vite 通过特殊的 import.meta.hot 对象暴露手动 HMR API。


必需的条件守卫

首先,请确保用一个条件语句守护所有 HMR API 的使用,这样代码就可以在生产环境中被 tree-shaking 优化:

if (import.meta.hot) {  // HMR 代码}


hot.accept(cb)

要接收模块自身,应使用 import.meta.hot.accept,参数为接收已更新模块的回调函数:

export const count = 1
if (import.meta.hot) { import.meta.hot.accept((newModule) => { console.log('updated: count is now ', newModule.count) })}


“接受” 热更新的模块被认为是 HMR 边界。


请注意,Vite 的 HMR 实际上并不替换最初导入的模块:如果 HMR 边界模块从某个依赖重新导出其导入,则它应负责更新这些重新导出的模块(这些导出必须使用 let)。此外,从边界模块向上的导入者将不会收到更新。


这种简化的 HMR 实现对于大多数开发用例来说已经足够了,同时允许我们跳过生成代理模块的昂贵工作。


hot.accept(deps, cb)

模块也可以接受直接依赖项的更新,而无需重新加载自身:

import { foo } from './foo.js'
foo()
if (import.meta.hot) { import.meta.hot.accept('./foo.js', (newFoo) => { // 回调函数接收到更新后的'./foo.js' 模块 newFoo.foo() })
// 也可以接受一个依赖模块的数组: import.meta.hot.accept( ['./foo.js', './bar.js'], ([newFooModule, newBarModule]) => { // 回调函数接收一个更新后模块的数组 } )}


hot.dispose(cb)

一个接收自身的模块或一个期望被其他模块接收的模块可以使用 hot.dispose 来清除任何由其更新副本产生的持久副作用:

function setupSideEffect() {}
setupSideEffect()
if (import.meta.hot) { import.meta.hot.dispose((data) => { // 清理副作用 })}


hot.data

import.meta.hot.data 对象在同一个更新模块的不同实例之间持久化。它可以用于将信息从模块的前一个版本传递到下一个版本。


hot.decline()

调用 import.meta.hot.decline() 表示此模块不可热更新,如果在传播 HMR 更新时遇到此模块,浏览器应该执行完全重新加载。


hot.invalidate()

现在调用 import.meta.hot.invalidate() 只是重新加载页面。


hot.on(event, cb)

监听自定义 HMR 事件。


浏览 11
点赞
评论
收藏
分享

手机扫一扫分享

举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

举报