vite3+vue3 HMR热更新无效 页面无法局部自动更新(需手动刷新页面)的问题解决

结论:Vite和Vue版本不兼容(Vite@3.2.10和Vue@3.4.31)

解决:降低Vue的版本到@3.3.4

下面是问题排查和解决过程:

一、现象

1、修改.vue单组件文件【LoginForm.vue】(修改了其<template>),但页面无法进行局部自动更新,但修改.ts、.js文件可以自动刷新页面。

2、vscode终端控制台可以打印【10:55:18 [vite] hmr update /src/views/sys/login/LoginForm.vue  】,浏览器控制台(级别:详细)也可以打印【[vite] hot updated: /src/views/sys/login/LoginForm.vue】,但页面就是不局部自动更新。

二、猜测及进一步测试

所以猜测是vite HMR对于.vue文件的处理可能存在问题。于是进一步分别修改<tempalte>、<script>、<style>三个部分的内容,发现只有改<style>部分的内容浏览器才会局部自动更新。合理猜测HMR(热模块替换)对于Vue组件的模板和脚本部分没有正常工作,而对于样式部分则正常工作。

三、查找资料

查看vite官网关于HRM热更新的资料

点击链接进去,是vite-plugin-vue(@vitejs/plugin-vue)【Vite 官方为 Vue3 提供的插件,@vitejs/plugin-vue为包依赖名】的github项目仓库。

所以“Vite内置了HMR到Vue单文件组件(SFC)” ==>“Vite内置了HMR到 vite-plugin-vue中”==>HMR 功能和@vitejs/plugin-vue有关。

于是了解@vitejs/plugin-vue

介绍:

@vitejs/plugin-vue 是一个针对 Vue 框架的 Vite 插件。它的主要功能是支持基于 Vite 构建的 Vue 项目,为 Vite 提供对 Vue 单文件组件(SFC)的支持。

具体来说,@vitejs/plugin-vue 可以在 Vite 构建过程中处理 Vue 单文件组件(SFC),将其转换为 JavaScript 模块以便在浏览器中使用。这个插件对SFC的解析“主要”是使用 Vue 3 的编译器(如:@vue/compiler-sfc)来处理 .vue 文件的<template><script>部分,使用postcss、css预处理器等来处理<style>部分。

因此,@vitejs/plugin-vue 使得 Vite 能够理解 Vue 的 SFC,并将其编译为浏览器可以执行的代码。而 Vite 的 HMR 功能则确保在编译过程中,当修改了 SFC 时,应用能够实时更新,从而提高开发效率。

了解完毕后,得出结论

Vite 内置的 HMR 功能与@vitejs/plugin-vue插件是密切相关的,而 @vitejs/plugin-vue对Vue3 单文件组件(SFC)的编译解析离不开Vue3模板编译器。因此,@vitejs/plugin-vue的版本和Vue3模板编译器(@vue/compiler-sfc)的版本息息相关。而Vite的版本决定了@vitejs/plugin-vue的版本,Vue的版本决定了@vue/compiler-sfc的版本,所以合理猜测考虑是Vite和Vue二者版本兼容性的问题。

之后进行代码审查:

四、问题解决

当前猜测不兼容的Vite@3.2.10和Vue@3.4.31版本如下:

vite@3.2.10(@types/node@17.0.45)(less@4.2.0)(terser@5.31.1):

    dependencies:

      esbuild: 0.15.18

      postcss: 8.4.39

      resolve: 1.22.8

      rollup: 2.79.1

    optionalDependencies:

      '@types/node': 17.0.45

      fsevents: 2.3.3

      less: 4.2.0

      terser: 5.31.1

vue@3.4.31(typescript@4.9.5):

    dependencies:

      '@vue/compiler-dom': 3.4.31

      '@vue/compiler-sfc': 3.4.31

      '@vue/runtime-dom': 3.4.31

      '@vue/server-renderer': 3.4.31(vue@3.4.31(typescript@4.9.5))

      '@vue/shared': 3.4.31

    optionalDependencies:

      typescript: 4.9.5

我将vue的版本降低到3.3.4之后,问题解决了。

  vue@3.3.4:

    dependencies:

      '@vue/compiler-dom': 3.3.4

      '@vue/compiler-sfc': 3.3.4

      '@vue/runtime-dom': 3.3.4

      '@vue/server-renderer': 3.3.4(vue@3.3.4)

      '@vue/shared': 3.3.4

之后我又尝试了其他版本组合

Vite@5.3.3和Vue@3.4.31最新版组合,测试通过,没有问题

 vite@5.3.3:

    dependencies:

      esbuild: 0.21.5

      postcss: 8.4.39

      rollup: 4.18.1

    optionalDependencies:

      fsevents: 2.3.3

  vue@3.4.31(typescript@5.5.3):

    dependencies:

      '@vue/compiler-dom': 3.4.31

      '@vue/compiler-sfc': 3.4.31

      '@vue/runtime-dom': 3.4.31

      '@vue/server-renderer': 3.4.31(vue@3.4.31(typescript@5.5.3))

      '@vue/shared': 3.4.31

    optionalDependencies:

      typescript: 5.5.3

Vite@3.0.2和Vue@3.2.33随机版组合,测试通过,没有问题

vite@https://registry.npmmirror.com/vite/-/vite-3.0.2.tgz(less@4.1.2)(terser@5.31.2):

    dependencies:

      esbuild: https://registry.npmmirror.com/esbuild/-/esbuild-0.14.54.tgz

      less: https://registry.npmmirror.com/less/-/less-4.1.2.tgz

      postcss: https://registry.npmmirror.com/postcss/-/postcss-8.4.39.tgz

      resolve: https://registry.npmmirror.com/resolve/-/resolve-1.22.8.tgz

      rollup: https://registry.npmmirror.com/rollup/-/rollup-2.72.0.tgz

      terser: https://registry.npmmirror.com/terser/-/terser-5.31.2.tgz

    optionalDependencies:

      fsevents: https://registry.npmmirror.com/fsevents/-/fsevents-2.3.3.tgz

 vue@https://registry.npmmirror.com/vue/-/vue-3.2.33.tgz:

    dependencies:

      '@vue/compiler-dom': https://registry.npmmirror.com/@vue/compiler-dom/-/compiler-dom-3.2.33.tgz

      '@vue/compiler-sfc': https://registry.npmmirror.com/@vue/compiler-sfc/-/compiler-sfc-3.2.33.tgz

      '@vue/runtime-dom': https://registry.npmmirror.com/@vue/runtime-dom/-/runtime-dom-3.2.33.tgz

      '@vue/server-renderer': https://registry.npmmirror.com/@vue/server-renderer/-/server-renderer-3.2.33.tgz(vue@3.2.33)

      '@vue/shared': https://registry.npmmirror.com/@vue/shared/-/shared-3.2.33.tgz

Vite@3.2.7和Vue@3.3.8随机版组合,测试通过,没有问题

 vite@^3.0.2:
  version "3.2.7"
  resolved "https://registry.npmmirror.com/vite/-/vite-3.2.7.tgz#35a62826bd4d6b778ae5db8766d023bcd4e7bef3"
  integrity sha512-29pdXjk49xAP0QBr0xXqu2s5jiQIXNvE/xwd0vUizYT2Hzqe4BksNNoWllFVXJf4eLZ+UlVQmXfB4lWrc+t18g==
  dependencies:
    esbuild "^0.15.9"
    postcss "^8.4.18"
    resolve "^1.22.1"
    rollup "^2.79.1"
  optionalDependencies:
    fsevents "~2.3.2"

vue@^3.2.33:
  version "3.3.8"
  resolved "https://registry.npmmirror.com/vue/-/vue-3.3.8.tgz#532ff071af24f6a69e5ecc53a66858a9ee874ffc"
  integrity sha512-5VSX/3DabBikOXMsxzlW8JyfeLKlG9mzqnWgLQLty88vdZL7ZJgrdgBOmrArwxiLtmS+lNNpPcBYqrhE6TQW5w==
  dependencies:
    "@vue/compiler-dom" "3.3.8"
    "@vue/compiler-sfc" "3.3.8"
    "@vue/runtime-dom" "3.3.8"
    "@vue/server-renderer" "3.3.8"
    "@vue/shared" "3.3.8" 

以上告一段落。

五、额外话

1、最好将项目的包版本锁定文件进行代码管理(使用Git或SVN),通常npm对应package-lock.json、yarn对应yarn.lock、pnpm对应pnpm-lock.yaml等。这样就不会出现团队协作开发时,一个成员并没有出现另一个成员出现的BUG,就很有可能是他们下载的依赖的版本不一致导致的问题,就比如上述HMR热更新的问题就是这样的情况。更进一步约束团队成员使用一样的包管理工具,在项目根目录下.npmr文件中配置相同的远程镜像。

2、项目进行依赖升级时要注意版本兼容性

3、 Vue2的SFC 编译器为vue-template-compiler

4、注意:从vue 3.2.13+和@vitejs/plugin-vue 1.9.0+开始,@vue/compiler-sfc不再需要作为对等依赖。即随着Vue和Vite的更新,特别是Vue 3.2.13和@vitejs/plugin-vue1.9.0的发布,这些版本内部已经包含了与@vue/compiler-sfc兼容的编译器或相关逻辑,因此不再需要开发者手动安装@vue/compiler-sfc作为对等依赖。

然而,在某些高级或特定的场景下,你可能还需要直接使用@vue/compiler-sfc来处理一些特定的任务,例如:

  1. 自定义SFC的编译过程:如果你需要自定义SFC的编译过程,比如修改模板编译的某些行为,你可能需要直接使用@vue/compiler-sfc来进行更底层的操作。
  2. 分析SFC的结构:@vue/compiler-sfc提供了将SFC解析为AST(抽象语法树)的能力,这对于需要进行SFC结构分析的场景(如代码高亮、代码格式化等)是非常有用的。
  3. 构建自定义工具链:如果你正在构建一个自定义的前端工具链,并希望在其中集成对SFC的支持,那么你可能需要直接使用@vue/compiler-sfc来处理SFC。

5、在npm(Node Package Manager)的版本号表示法中,^~是两个常用的符号,用于指定依赖包的版本范围。在实际项目中,通常推荐使用^(Caret,因为它允许你获取到同一主版本下的新功能和bug修复。然而,如果你的项目需要极高的稳定性,或者你希望严格控制依赖的版本更新,那么~(Tilde可能是一个更好的选择(只接受次要更新,通常是bug修复)。

  1. ^(Caret)符号
    当版本号使用^开头时,它表示接受当前指定的主版本号(major version)下的任何更新。例如,"vite": "^3.0.2"意味着npm将接受任何3.x.x版本的vite,其中x可以是任何数字,但主版本号(在这个例子中是3)必须保持不变。

    这意味着,如果当前安装的版本是3.0.2,那么当3.0.33.1.03.2.5等版本发布时,npm会尝试更新到这些版本,但不会更新到4.0.0或更高的版本,因为这些版本的主版本号已经改变。

  2. ~(Tilde)符号
    ~符号则更为保守,它只接受当前指定的次版本号(minor version)下的任何更新,但主版本号和次版本号都必须保持不变。例如,"vite": "~3.0.2"将只接受3.0.x版本的更新,其中x可以是任何数字,但主版本号(3)和次版本号(0)都不能改变。因此,3.0.33.0.4等版本是允许的,但3.1.0或更高版本则不允许。

  3. 指定具体版本号:例如"vite": "3.0.2",这将只安装该确切版本,而不会接受任何更新。
  4. 使用范围:例如,"vite": ">=3.0.0 <4.0.0"将匹配所有大于或等于3.0.0但小于4.0.0的版本

6、@vitejs/plugin-vue 是主要为 Vue 3 提供的。然而,对于 Vue 2,虽然没有官方的@vitejs/plugin-vue直接支持,但社区提供了如@vitejs/plugin-vue2 这样的插件来实现在 Vite 中对 Vue 2 的支持。

  • 15
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
vite 是一个由 Vue.js 团队开发的工具,它可以用于打包和开发 Vue.js 项目。vite 的出现是为了解决传统打包工具的一些问题,并且对于使用 Vue.js 进行开发的项目来说,vite 的支持性更好。 vite 的优势之一是它的开发服务器采用了 ES 模块的原生导入方式,这使得项目的启动速度更快。另外,vite 还支持热模块替换(HMR),它可以在开发过程中实时更新修改的部分,提高开发效率。 对于使用 vite 进行开发的 Vue.js 项目,你可以选择使用 yyg-cli 这个封装并发布到 npmjs 上的脚手架。yyg-cli 可以帮助你快速创建基于 vite 和 Vue3 的全家桶项目,省去手动添加和配置的步骤。 使用 yyg-cli 创建项目后,你可以在里面集成 vue-router、pinia、element plus 等库,以满足项目的求。这样可以简化项目的搭建过程,并提高开发效率。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [【vue3】使用vite构建vue3项目](https://blog.csdn.net/m0_61118311/article/details/129843808)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* *3* [基于 vite 创建 vue3 全家桶项目(vite + vue3 + tsx + pinia)](https://blog.csdn.net/youyacoder/article/details/126835676)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值