vitejs / vite-plugin-vue

Vite Vue Plugins
MIT License
487 stars 153 forks source link

热更新失效 #7

Open ningbnii opened 2 years ago

ningbnii commented 2 years ago

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

poyoho commented 2 years ago

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

and modify script will hmr

laola2013 commented 2 years ago

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

poyoho commented 2 years ago

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 commented 2 years ago

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 commented 2 years ago

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

and modify script will hmr

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

laola2013 commented 2 years ago
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 commented 2 years ago
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 commented 2 years ago

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 commented 2 years ago

我测试了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 commented 2 years ago

我测试了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 commented 1 year ago

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

wangjieBABA commented 1 year ago

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

feiyayshx commented 1 year ago

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

Gxmg commented 1 year ago

没有办法解决吗?

little-buddy commented 11 months ago

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

YellRes commented 9 months ago

@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 commented 6 months ago

动画

测试用到的版本如下:

{
  "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还是特性吗?为什么这么长时间没有解决这问题