vite hmr update 不执行问题

795 阅读3分钟

vue3 已经出了一段时间了,其生态来讲应该已经比较健壮了,但是今天在使用vite+vue3的时候,出现了一个棘手的问题,就是更新.vue文件的时候, 没有热更新,浏览器无响应,网页刷新也不行,只能通过重新run来解决, 这个问题还只涉及我一个公共components里面的一个组件的修改, 其他组件还不受影响, 找了半天才解决这个问题。

问题场景

  • 首先来看问题如何出现的, 当我们在使用 vite + vue3 的项目的时候, 每一次修改文件, 那么控制台都会进行一个 hrm update 的操作 如下: image.png 但是在我更新我其中一个组件的时候, 每次只会在第一次更新的时候, 执行一次 hrm update , 大家可以看上图,每次更新同一个问题,都会执行, 其会在后面显示次数 如(x2), 但唯独我这个文件不会, 第二次更新的时候没有热更新,且浏览器无响应。刷新无相应。必须重新run。 如下图: image.png
  • 文件配置如下, 首先是 package.json 然后是 vite.config :
  • package.json
{
  "name": "my-vue-app",
  "private": true,
  "version": "0.0.0",
  "scripts": {
    "dev": "vite",
    "build": "vue-tsc && vite build",
    "preview": "vite preview",
    "prepare": "husky install",
    "pre-commit": "lint-staged",
    "lint-staged:js": "eslint --ext .js,.jsx,.ts,.tsx ",
    "lint-staged": "lint-staged"
  },
  "dependencies": {
    "@element-plus/icons-vue": "^2.3.1",
    "@vueuse/core": "^10.9.0",
    "axios": "^1.6.8",
    "crypto-js": "^4.2.0",
    "element-plus": "^2.6.3",
    "nprogress": "^0.2.0",
    "path-browserify": "^1.0.1",
    "pinia": "^2.1.7",
    "pinia-plugin-persistedstate": "^3.2.1",
    "vue": "^3.4.31",
    "vue-router": "^4.3.0",
    "unplugin-vue-define-options": "^1.3.5"
  },
  "lint-staged": {
    "**/*.{js,jsx,ts,tsx,vue}": [
      "eslint --fix",
      "prettier --write",
      "git add"
    ],
    "*.{scss,less,styl,html}": [
      "prettier --write"
    ]
  },
  "devDependencies": {
    "@types/axios": "^0.14.0",
    "@types/crypto-js": "^4.2.2",
    "@types/node": "^20.11.30",
    "@types/path-browserify": "^1.0.2",
    "@typescript-eslint/eslint-plugin": "^7.3.1",
    "@typescript-eslint/parser": "^7.3.1",
    "@vitejs/plugin-vue": "^5.0.4",
    "eslint": "^8.34.0",
    "eslint-import-resolver-alias": "^1.1.2",
    "eslint-plugin-import": "^2.29.1",
    "eslint-plugin-prettier": "^5.1.3",
    "eslint-plugin-vue": "^9.23.0",
    "husky": "^8.0.0",
    "less": "^4.2.0",
    "lint-staged": "^10.5.4",
    "mockjs": "^1.1.0",
    "prettier": "^3.2.5",
    "typescript": "^5.4.2",
    "unplugin-auto-import": "^0.17.5",
    "unplugin-vue-components": "^0.26.0",
    "vite": "^5.3.3",
    "vite-plugin-mock": "2.9.6",
    "vite-plugin-svg-icons": "^2.0.1",
    "vite-svg-loader": "^5.1.0",
    "vite-plugin-vue-setup-extend": "^0.4.0",
    "vue-tsc": "^1.8.27"
  }
}
  • vite.config
    可以看到我这个文件里面 server 的配置 有一行是 hmr: true ,这个也是找了网上一些方案, 配置了一下,其实这个删掉我也试了,无所谓, 因为本身 vite 配置的默认值就是 true
import { defineConfig, loadEnv } from 'vite';
import vue from '@vitejs/plugin-vue';
import path from 'path';
import { viteMockServe } from 'vite-plugin-mock';
// element-plus按需引入
import AutoImport from 'unplugin-auto-import/vite';
import VueSetupExtend from 'vite-plugin-vue-setup-extend';
import Components from 'unplugin-vue-components/vite';
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers';
// svg
import { createSvgIconsPlugin } from 'vite-plugin-svg-icons';
import svgLoader from 'vite-svg-loader';
import DefineOptions from 'unplugin-vue-define-options/vite'; // 给标签式 setup 加 name

// https://vitejs.dev/config/
/**
 * 配置 Vite 开发环境的函数
 *
 * @param config - Vite 提供的配置对象,包含当前的命令和模式等信息
 * @returns 返回一个配置对象,用于定制 Vite 的行为
 */
export default defineConfig((config) => {
  const { command, mode } = config;
  const env = loadEnv(mode, process.cwd());
  return {
    base: './',
    define: {
      'process.env': {},
    },
    // 配置需要使用的插件列表
    plugins: [
      viteMockServe({
        // 只在开发阶段开启 mock 服务,mock和后端服务器接口能共存,可以通过配置来区分
        localEnabled: command === 'serve',
      }),
      vue(),
      DefineOptions(),
      AutoImport({
        resolvers: [ElementPlusResolver()],
      }),
      Components({
        resolvers: [ElementPlusResolver()],
      }),
      // * name 可以写在 script 标签上
      VueSetupExtend(),
      createSvgIconsPlugin({
        iconDirs: [path.resolve(process.cwd(), 'src/assets/icons')],
        symbolId: 'icon-[dir]-[name]',
      }),
      // * vite-svg-loader支持,可以直接引入svg图标当作组件使用
      svgLoader(),
    ],
    resolve: {
      alias: {
        // 配置别名
        '@': path.resolve(__dirname, './src'),
      },
    },
    css: {
      preprocessorOptions: {
        less: {
          math: 'always',
          // 允许使用 js 表达式
          javascriptEnabled: true,
          // 引入全局变量
          additionalData: `@import "${path.resolve(__dirname, 'src/styles/common.less')}";`,
        },
      },
    },
    server: {
      hmr: true,
      host: 'localhost',
      port: Number(env.VITE_APP_PORT), // 服务器端口,从环境变量读取
      proxy: {
        [env.VITE_APP_BASE_API]: {
          target: 'https://bizfw.dev.d2d.ai/gateway', // 代理地址
          changeOrigin: true, // 允许跨域
          // rewrite: (path) => path.replace(/^\/rest/, ''), // 重写路径,移除前缀
        },
      },
    },
  };
});

问题解决

  • 首先肯定是网上看看大家有没有遇到这种情况, 搜到的很多都是一些命名不规范,产生此类问题的,而 官方库 github.com/vitejs/vite… 里面也有很多记录,大家也可以查看。
  • 我之前一个同样的项目是没有这个问题的,我详细对照了两个项目的包版本,发现差异还是比较大,然后我把有关vue 的版本都进行了降低,和我之前的项目进行了同步,再重新 run 这个项目 就没有问题了。 下面是版本差异对照。
    image.png 我觉得这里可能降低版本的只需要 vite-plugin-vue 就够了~