自动查找接收模块的更新
// main.js
import "./style.css";
import { render } from "./renderA";
render();
// 判断是否有 hot,因为生产版本没有 hot
if (import.meta.hot) {
import.meta.hot.accept();
}
// renderA.js
export function render() {
document.querySelector("#app").innerHTML = `
<h1>Hello Vite!</h1>
<a href="https://vitejs.dev/guide/features.html" target="_blank">
Documentation
</a>
`;
}
- 当我们修改了
renderA
模块,vite 会自动查找我们引入的模块是否有更新,有更新会执行模块中被调用方法 - 当我们修改了
renderA
模块中的render
方法,由于在main.js
中被引用,vite 检测到了renderA
更新,main.js
会重新执行render
方法只更新我们想更新的模块
```javascript // main.js import “./style.css”;
import { render } from “./renderA”;
render();
// 判断是否有 hot,因为生产版本没有 hot if (import.meta.hot) { // 如果模块没有被热更新接受,就会走刷新页面 import.meta.hot.accept([‘./style.css’]); }
- 当我们 `accept` 函数中传入了数组,指定的引用更新时会进行热更新,没有指定的引用更新时会进行页面刷新
- 当我们 修改了 `renderA` 模块,由于我们没有指定处理这个模块的热更新,所以页面会刷新
<a name="c3G6s"></a>
# 处理我们想更新的模块
```javascript
// main.js
import "./style.css";
import { render } from "./renderA";
render();
// 判断是否有 hot,因为生产版本没有 hot
if (import.meta.hot) {
// 如果模块没有被热更新接受,就会走刷新页面
import.meta.hot.accept(["./renderA"], ([newA]) => {
newA.render(); // 读取代码中的方法
});
}
- 如果
accept
中只接收一个数组,那这个时候只会接受这个数组引用模块的更新,文件本身不会进行更新,需要在文件本身进行更新的处理 accept(["./renderA"]
接受了renderA
模块的更新,但是main.js
本身不会更新,需要通过回调来处理更新处理 side effect
问题
如果我们不是通过暴露函数,通过外面引用执行,而是直接在模块中执行某些行为,就会产生副作用,造成不可控制,内存溢出等等``javascript // renderA.js export function render() { document.querySelector("#app").innerHTML =
Hello Vite!
Documentation `; }
let index = 1; // side effet setInterval(() => { console.log(index++); }, 1000);
- 我们在 `renderA` 模块中定义了定时器,在 `main.js` 中引用这个模块,就会自动执行定时器,导致我们无法控制此定时器
<a name="p6oGc"></a>
## 处理
在模块中监听模块的卸载
```javascript
let index = 0;
// side effet
const timer = setInterval(() => {
console.log(index++);
}, 1000);
if (import.meta.hot) {
// 当模块被卸载时
import.meta.hot.dispose(() => {
if (timer) clearInterval(timer);
});
}
保留当前状态
问题
当我们修改代码时,不想让我们操作过的数据重新开始,就需要保留状态
let timer = null;
let index = 0;
export function render() {
timer = setInterval(() => {
index++;
document.querySelector("#app").innerHTML = `
<h1>Hello Vite!</h1>
<a href="https://vitejs.dev/guide/features.html" target="_blank">
documentation${index}
</a>
`;
}, 1000);
}
if (import.meta.hot) {
// 当模块被卸载时
import.meta.hot.dispose(() => {
if (timer) clearInterval(timer);
});
}
- 每次页面刷新,
index
都会被重置为 0 的状态,如果我们想保留 index 值,就需要做一些保留状态的处理处理
import.meta.hot.data
保存同一个模块中,热更新之前的状态 ```javascript let timer = null; // 需要判断是否有cache和getIndex let index = import.meta.hot.data?.cache?.getIndex() ?? 0;
export function render() {
timer = setInterval(() => {
index++;
document.querySelector(“#app”).innerHTML = <h1>Hello Vite!</h1>
<a href="https://vitejs.dev/guide/features.html" target="_blank">
11Documentation${index}
</a>
;
}, 1000);
}
if (import.meta.hot) { // data本身无法修改,只能在data中添加内容 // import.meta.hot.data.index = index; 直接赋值是个原始类型,初始化时赋值为0,后面一直为0 import.meta.hot.data.cache = { // 赋值对象时一个引用类型 getIndex() { return index; }, }; // 当模块被卸载时 import.meta.hot.dispose(() => { if (timer) clearInterval(timer); }); }
<a name="Mwpkg"></a>
# 主模块 热更新和强制刷新
```javascript
// main.js
import "./style.css";
import { render } from "./renderA";
render();
// 判断是否有 hot,因为生产版本没有 hot
if (import.meta.hot) {
// 如果模块没有被热更新接受,就会走刷新页面
import.meta.hot.accept(["./renderA"], ([newA]) => {
// console.log(import.meta.hot.data);
newA.render(); // 读取代码中的方法
});
}
此时我们在
main
中修改代码,是会刷新页面的,如果想让main
也保持热更新,需要做如下处理// 判断是否有 hot,因为生产版本没有 hot if (import.meta.hot) { // 如果模块没有被热更新接受,就会走刷新页面 import.meta.hot.accept(["./renderA"], ([newA]) => { // console.log(import.meta.hot.data); newA.render(); // 读取代码中的方法 }); import.meta.hot.accept(() => {}); // 保证 main.js 修改时,不重新刷新页面,也进行热更新 }
如果想让
main
页面强制刷新,可以使用如下方法import.meta.hot.decline()
// 判断是否有 hot,因为生产版本没有 hot if (import.meta.hot) { // 如果模块没有被热更新接受,就会走刷新页面 import.meta.hot.accept(["./renderA"], ([newA]) => { // console.log(import.meta.hot.data); newA.render(); // 读取代码中的方法 }); // import.meta.hot.accept(() => {}); // 保证 main.js 修改时,不重新刷新页面,也进行热更新 import.meta.hot.decline(); }
强制在 accept 之后,浏览器刷新
// 判断是否有 hot,因为生产版本没有 hot if (import.meta.hot) { // 如果模块没有被热更新接受,就会走刷新页面 import.meta.hot.accept(["./renderA"], ([newA]) => { // console.log(import.meta.hot.data); if (newA.index > 15) { // 如果大于 5 import.meta.hot.invalidate(); // 强制在 accept 之后,浏览器刷新 } else { newA.render(); // 读取代码中的方法 } }); import.meta.hot.accept(() => {}); // 保证 main.js 修改时,不重新刷新页面,也进行热更新 // import.meta.hot.decline(); }