Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

热更新失效 #7

Open
7 tasks done
ningbnii opened this issue Jan 11, 2022 · 17 comments
Open
7 tasks done

热更新失效 #7

ningbnii opened this issue Jan 11, 2022 · 17 comments
Labels
bug Something isn't working feat: hmr

Comments

@ningbnii
Copy link

ningbnii commented Jan 11, 2022

Describe the bug

在index.vue中import testClass,这时候修改testClass,可以输出console。但是修改index.vue后,再次修改testClass,就不会输出console了

Reproduction

https://github.com/ningbnii/vite2_vue3_hmr_test

System Info

  System:
    OS: Windows 10 10.0.17763
    CPU: (8) x64 Intel(R) Core(TM) i7-9700 CPU @ 3.00GHz
    Memory: 3.44 GB / 15.95 GB
  Binaries:
    Node: 16.12.0 - C:\Program Files\nodejs\node.EXE
    Yarn: 1.22.5 - C:\Program Files (x86)\Yarn\bin\yarn.CMD
    npm: 8.1.3 - C:\Program Files\nodejs\npm.CMD
  Browsers:
    Internet Explorer: 11.0.17763.2145
  npmPackages:
    @vitejs/plugin-vue: ^2.0.1 => 2.0.1
    vite: ^2.7.10 => 2.7.10

Used Package Manager

yarn

Logs

No response

Validations

@ningbnii ningbnii reopened this Jan 11, 2022
@poyoho
Copy link
Member

poyoho commented Jan 20, 2022

would you need to rerun script when modifying template and style? 🤔

and modify script will hmr

@laola2013
Copy link

遇到typeError错误时,即使修复问题后,页面也是无法进行热更新,必须手动重新加载页面,之后的热更才是正常的

@poyoho
Copy link
Member

poyoho commented Jan 21, 2022

I guess vite call vue runtime interface to rerender the components, but got a error will destroy the component, so we can't rerender only reload 😂

@laola2013
Copy link

laola2013 commented Jan 25, 2022

I guess vite call vue runtime interface to rerender the components, but got a error will destroy the component, so we can't rerender only reload 😂

应该是这样的,其实对于js文件而言,不存在这个问题,因为vite对于.js.vue 采用了不同的更新方式,前者用的是page reload,而后者采用的是hmr update
目前我的解决方式是:对于.vue的文件添加了额外的文件监听器,更新时直接page reload,这样做比较难受的点是开发体验上稍微差了一点。

@ningbnii
Copy link
Author

would you need to rerun script when modifying template and style? 🤔

and modify script will hmr

修改.vue文件后,再修改.js文件,就不会热更新了,重新启动一下项目,再更改.js文件,就又可以热更新了

@laola2013
Copy link

laola2013 commented Jan 27, 2022

System:
    OS: Windows 10 10.0.17763
    CPU: (8) x64 Intel(R) Core(TM) i7-9700 CPU @ 3.00GHz
    Memory: 3.44 GB / 15.95 GB

would you need to rerun script when modifying template and style? 🤔
and modify script will hmr

修改.vue文件后,再修改.js文件,就不会热更新了,重新启动一下项目,再更改.js文件,就又可以热更新了

可能因为我是macOS,也有可能是因为我用的是@vitejs/plugin-vue@1.10.2,所以没有出现你说的这种情况,vite内部在采用的是chokidar的文件系统监听器,在不同系统之间的表现可能存在差异(bug),之后再看一下,有没有更好的处理方式

@ningbnii
Copy link
Author

System:
    OS: Windows 10 10.0.17763
    CPU: (8) x64 Intel(R) Core(TM) i7-9700 CPU @ 3.00GHz
    Memory: 3.44 GB / 15.95 GB

would you need to rerun script when modifying template and style? 🤔
and modify script will hmr

修改.vue文件后,再修改.js文件,就不会热更新了,重新启动一下项目,再更改.js文件,就又可以热更新了

可能因为我是macOS,也有可能是因为我用的是@vitejs/plugin-vue@1.10.2,所以没有出现你说的这种情况,vite内部在采用的是chokidar的文件系统监听器,在不同系统之间的表现可能存在差异(bug),之后再看一下,有没有更好的处理方式

我测试了macOS,使用了@vitejs/plugin-vue@1.10.2,问题依然存在,我截图说明了一下测试流程
1、yarn dev
image
2、修改index.vue
image
3、修改testClass.js
image

@poyoho
Copy link
Member

poyoho commented Jan 30, 2022

Vite splits .vue into two files: .css / .js link

CSS error report only needs to re-insert the head node.

But the js error will cause the internal execution error of vue, because the template+script regenerated by vite will be updated and executed when updating (https://github.com/vuejs/core/blob/main/packages/runtime-core/src/ hmr.ts#L78-L99)

However, after the error is reported, the last vdom will be destroyed and the patch(instance.update()) of the rerender cannot be executed.


vite内部将.vue拆成两个文件 .css / .js

css报错只需要重新插入head节点。

但是js报错会导致vue内部执行错误,因为在更新的时候会将vite重新生成的template+script 更新执行 https://github.com/vuejs/core/blob/main/packages/runtime-core/src/hmr.ts#L78-L99

但是报错后会破坏上次的vdom 导致没办法执行rerender的patch(instance.update()).

@poyoho
Copy link
Member

poyoho commented Jan 31, 2022

我测试了macOS,使用了@vitejs/plugin-vue@1.10.2,问题依然存在,我截图说明了一下测试流程

may be the rerender script don't exec the setup script again.

setup lifecycle will exec in the Component setup first time.and the Component is not exec the destroy so no exec the setup Script.

you can chance to destroy the <route-view> and mount the <route-view> that will be exec.😀

@ningbnii
Copy link
Author

我测试了macOS,使用了@vitejs/plugin-vue@1.10.2,问题依然存在,我截图说明了一下测试流程

may be the rerender script don't exec the setup script again.

setup lifecycle will exec in the Component setup first time.and the Component is not exec the destroy so no exec the setup Script.

you can chance to destroy the <route-view> and mount the <route-view> that will be exec.😀

但是不修改.vue,只修改.js的情况下,页面是可以热更新的,只有在修改了.vue的前提下,再修改.js才不会热更新

@enjoy-wind
Copy link

我本地Mac ,js始终无法更新

@wangjieBABA
Copy link

当我引入一些自定义组件的时候,页面会报出警告,提示我无法识别这个自定义组件,从而无法在页面显示。重启之后就显示正常!

@feiyayshx
Copy link

feiyayshx commented Apr 4, 2023

遇到同样问题,父组件引入新创建的子组件,热更新编译报错,提示不认识子组件;js文件添加变量引入到父组件也会报错,每次都要重新启动项目。@vitejs/plugin-vue版本3.1.0

@Gxmg
Copy link

Gxmg commented May 4, 2023

没有办法解决吗?

@little-buddy
Copy link

快2年了,也没有解决呀,vite的hmr限制写法太多了 😂

@YellRes
Copy link

YellRes commented Jan 11, 2024

@vitejs/plugin-vue 有这段代码

// check if the template is the only thing that changed
if (prevDescriptor && isOnlyTemplateChanged(prevDescriptor, descriptor)) {
  output.push(`export const _rerender_only = true`)
}
output.push(
  `import.meta.hot.accept(mod => {`,
  `  if (!mod) return`,
  `  const { default: updated, _rerender_only } = mod`,
  `  if (_rerender_only) {`,
  `    __VUE_HMR_RUNTIME__.rerender(updated.__hmrId, updated.render)`,
  `  } else {`,
  `    __VUE_HMR_RUNTIME__.reload(updated.__hmrId, updated)`,
  `  }`,
  `})`,
)

中有一个_rerender_only的变量,当@vitejs/plugin-vue发现当前代码非首次构建,而且当前只有template标签中发生变化的时候,就会把_rerender_only 设置为true。

_rerender_only 为true时,热更新会执行 VUE_HMR_RUNTIME.rerender(xx) 这个函数并不会重新获取组件中的最新的状态值(例如重新执行setup函数得到最新的值),而从外面导入的值就在setup函数中。

其中判断是否只有template发生变化的isOnlyTemplateChanged代码如下:

export function isOnlyTemplateChanged(
  prev: SFCDescriptor,
  next: SFCDescriptor,
): boolean {
  return (
    !hasScriptChanged(prev, next) &&
    prev.styles.length === next.styles.length &&
    prev.styles.every((s, i) => isEqualBlock(s, next.styles[i])) &&
    prev.customBlocks.length === next.customBlocks.length &&
    prev.customBlocks.every((s, i) => isEqualBlock(s, next.customBlocks[i]))
  )
}

当script没有发生变化,styles没有发生变化,customBlock没有发生变化的时候,这边默认认为只有template发生了变化。但是当我们修改了外面引入的文件时候同样满足了上述情形,导致了插件认为我们只需要rerender,导致没有获取到最新的setup中的值。

@ys3322
Copy link

ys3322 commented Apr 23, 2024

动画

  • 在使用最新版vite提供的vue模板项目中,也存在热更新问题。
  • 一旦修改了template中任意代码,就会导致外部引入的js热更新失效。
  • 修改script脚本中的任意代码,就可以恢复外部js文件的热更新
  • 具体操作可以看我上述动态图片

测试用到的版本如下:

{
  "name": "my-vite-vue-demo",
  "private": true,
  "version": "0.0.0",
  "type": "module",
  "scripts": {
    "dev": "vite",
    "build": "vite build",
    "preview": "vite preview"
  },
  "dependencies": {
    "vue": "^3.4.21"
  },
  "devDependencies": {
    "@vitejs/plugin-vue": "^5.0.4",
    "sass": "^1.75.0",
    "vite": "^5.2.0"
  }
}

** 这是bug还是特性吗?为什么这么长时间没有解决这问题 **

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working feat: hmr
Projects
None yet
Development

No branches or pull requests

12 participants