带你玩转 Vite + Vue3 高低版本常用玩法 | 京东云技术团队

一、首先来个 Vite 的通用简介

Vite 是一种新型前端构建工具,在我们保险前端项目中已经推动并应用很久了,Vite 能够显著降低构建时间,提升前端开发效率。

它主要由两部分组成:

Vite 还提供了强大的扩展性,可通过其 插件 APIJavaScript API 进行扩展,并提供完整的类型支持。

二、Vite 的优势,为什么使用 Vite ?

当我们开始构建越来越大型的应用时,需要处理的 JavaScript 代码量也呈指数级增长。包含数千个模块的大型项目相当普遍。基于 JavaScript 开发的工具就会开始遇到性能瓶颈:通常需要很长时间(甚至是几分钟!)才能启动开发服务器,即使使用模块热替换(HMR),文件修改后的效果也需要几秒钟才能在浏览器中反映出来。如此循环往复,严重影响开发人员的效率。

当冷启动开发服务器时,基于打包器的方式启动必须优先抓取并构建你的整个应用,然后才能提供服务,如果项目很大,导致的一个必然结果就是,服务启动很慢,热更新很慢,效率降低。Vite 只需要在浏览器请求源码时进行转换并按需提供源码。根据情景动态导入代码,即只在当前屏幕上实际使用时才会被处理,节省启动及更新时间。

如下图是新旧项目启动时长对比,Vite 启动速度,快了 30 多倍

常规的通过 webpack 启动的服务,基于打包器启动,整个重新构建,即使将构建内容放到缓存中,更新速度也会随着应用体积增长而直线下降:

Vite 在原生 ESM 基础上执行 HMR,Vite 只需要精确地使已编辑的模块与其最近的 HMR 边界之间的链失活(大多数时候只是模块本身),使得无论应用大小如何,HMR 始终能保持快速更新:

三、Vite 为我们开发提升了很大的效率,但是也会有一些小问题

1、使用 Vite + Vue3 +Element-plus 或者其他 UI 库,按需加载使用时,多人开发,每人页面重新 reload 了吗🤓?

2、低版本 Vite(2.9以下)配置 Preview 的 proxy 时,是不是不生效🤓?

3、低版本 Vite 配合 unocss 设置样式后,是不是热更新不生效🤓?

4、部分依赖包,使用京东镜像,是不是无法下载🤓?

如果你遇到了以上问题,那这边文章可以帮助你解决困惑!

四、解决页面 reload 问题:高低版本 Vite 解决方法不同

  • 原因:UI 库配置按需加载,点击跳转新页面,导致重新 reload 页面
  • 情况:高低版本 Vite 解决页面 reload 方法不同

问题现象如下,上方图片页面会 reload会有一段时间白屏,下方图片中文件 preload:

1、Vite 低版本(v2.9以下)页面 reload 解决方法;

  • 解决方法:提前进行依赖包的预加载,可通过如下两种方法配置,推荐方法b(因为低版本有现成插件);
  • 通过这些配置,就能够使页面 reload 在多人开发时只进行一次。

注意事项(低版本 Vite 的 bug,高版本已经修复):

  • 使用 unocss 时,热更新会失效,需要手动刷新页面,如果不使用 unocss 影响不大

方法a、通过手动配置 vite.config.ts 文件的 optimizeDeps 选项;

css 复制代码
// vite.config.js
{
    ...
    optimizeDeps: {
        include: [
            'vue',
            'vue-router',
            'pinia',
            '@element-plus/icons-vue',
            'driver.js',
            'element-plus',
            'element-plus/es',
            'element-plus/es/components/alert/style/index',
            'element-plus/es/components/badge/style/index',
            'element-plus/es/components/breadcrumb-item/style/index',
            'element-plus/es/components/breadcrumb/style/index',
            'element-plus/es/components/button/style/index',
            'element-plus/es/components/card/style/index'
            ...
        ]
    }
}

方法b、使用现成的插件 vite-plugin-optimize-persist vite-plugin-package-config (推荐原因: 自动会生成预加载配置文件 optimizeDeps),通用配置如下:

😂遗憾的是高版本(v2.9及以上失效)配置无效,有兴趣的话,可以试着修改下源码。

javascript 复制代码
// vite.config.ts
// 两个插件组合使用,会自动生成 optimizeDeps 配置,默认生成到 package.json 文件中,可通过 PkgConfig() 修改生成目录
import OptimizationPersist from 'vite-plugin-optimize-persist'
import PkgConfig from 'vite-plugin-package-config'

export default {
  ...
  plugins: [
    ...
    PkgConfig(),
    OptimizationPersist()
  ]
}

2、Vite 高版本(v4+)页面 reload 解决方法:

  • 解决方法:上述两个插件已被弃用,只能自己配置 optimizeDeps 选项,提前进行依赖包的预加载;

全量配置案例如下,备注:如果项目中使用,根据项目需要进行相应依赖包的配置,否则会出现首屏加载过慢的问题,类似我们常规使用的 webpack 一样;

ruby 复制代码
// vite.config.js

{
    ...
    optimizeDeps:{
         include: [
            '@element-plus/icons-vue',
            '@tinymce/tinymce-vue',
            '@vueuse/core',
            '@vueuse/shared',
            'axios',
            'clipboard',
            'codemirror',
            'codemirror/addon/lint/json-lint',
            'codemirror/addon/lint/lint',
            'codemirror/mode/css/css',
            'codemirror/mode/htmlmixed/htmlmixed',
            'codemirror/mode/javascript/javascript',
            'driver.js',
            'element-plus',
            'element-plus/es',
            'element-plus/es/components/alert/style/index',
            'element-plus/es/components/badge/style/index',
            'element-plus/es/components/breadcrumb-item/style/index',
            'element-plus/es/components/breadcrumb/style/index',
            'element-plus/es/components/button/style/index',
            'element-plus/es/components/card/style/index',
            'element-plus/es/components/cascader/style/index',
            'element-plus/es/components/check-tag/style/index',
            'element-plus/es/components/checkbox-group/style/index',
            'element-plus/es/components/checkbox/style/index',
            'element-plus/es/components/col/style/index',
            'element-plus/es/components/color-picker/style/index',
            'element-plus/es/components/config-provider/style/index',
            'element-plus/es/components/date-picker/style/index',
            'element-plus/es/components/dialog/style/index',
            'element-plus/es/components/divider/style/index',
            'element-plus/es/components/drawer/style/index',
            'element-plus/es/components/dropdown-item/style/index',
            'element-plus/es/components/dropdown-menu/style/index',
            'element-plus/es/components/dropdown/style/index',
            'element-plus/es/components/empty/style/index',
            'element-plus/es/components/form-item/style/index',
            'element-plus/es/components/form/style/index',
            'element-plus/es/components/icon/style/index',
            'element-plus/es/components/input-number/style/index',
            'element-plus/es/components/input/style/index',
            'element-plus/es/components/link/style/index',
            'element-plus/es/components/loading/style/index',
            'element-plus/es/components/menu-item/style/index',
            'element-plus/es/components/menu/style/index',
            'element-plus/es/components/message-box/style/index',
            'element-plus/es/components/message/style/index',
            'element-plus/es/components/notification/style/index',
            'element-plus/es/components/option/style/index',
            'element-plus/es/components/pagination/style/index',
            'element-plus/es/components/popover/style/index',
            'element-plus/es/components/progress/style/index',
            'element-plus/es/components/radio-group/style/index',
            'element-plus/es/components/radio/style/index',
            'element-plus/es/components/row/style/index',
            'element-plus/es/components/scrollbar/style/index',
            'element-plus/es/components/select/style/index',
            'element-plus/es/components/space/style/index',
            'element-plus/es/components/step/style/index',
            'element-plus/es/components/steps/style/index',
            'element-plus/es/components/sub-menu/style/index',
            'element-plus/es/components/switch/style/index',
            'element-plus/es/components/tab-pane/style/index',
            'element-plus/es/components/table-column/style/index',
            'element-plus/es/components/table/style/index',
            'element-plus/es/components/tabs/style/index',
            'element-plus/es/components/tag/style/index',
            'element-plus/es/components/timeline-item/style/index',
            'element-plus/es/components/timeline/style/index',
            'element-plus/es/components/tooltip/style/index',
            'element-plus/es/components/transfer/style/index',
            'element-plus/es/components/upload/style/index',
            'element-plus/es/components/popconfirm/style/index',
            'element-plus/es/components/backtop/style/index',
            'element-plus/es/components/affix/style/index',
            'element-plus/es/components/statistic/style/index',
            'element-plus/es/components/tree/style/index',
            'element-plus/es/components/tree-v2/style/index',
            'element-plus/es/components/tree-select/style/index',
            'element-plus/es/components/table-v2/style/index',
            'element-plus/es/components/skeleton/style/index',
            'element-plus/es/components/skeleton-item/style/index',
            'element-plus/es/components/collapse/style/index',
            'element-plus/es/components/collapse-item/style/index',
            'element-plus/es/components/collapse-transition/style/index',
            'element-plus/es/components/carousel/style/index',
            'element-plus/es/components/carousel-item/style/index',
            'element-plus/es/components/calendar/style/index',
            'element-plus/es/components/badge/style/index',
            'element-plus/es/components/avatar/style/index',
            'element-plus/es/components/aside/style/index',
            'element-plus/es/locale/lang/zh-cn',
            'fuse.js',
            'js-base64',
            'js-cookie',
            'js-file-download',
            'nprogress',
            'pako',
            'path-browserify',
            'path-to-regexp',
            'pinia',
            'prismjs',
            'qs',
            'screenfull',
            'sortablejs',
            'vue',
            'vue-json-pretty',
            'vue-router',
            'vuedraggable' 
         ]
    }
}

五、解决 Vite 低版本(v2.9以下),preview 配置 proxy 不生效:

问题原因:低版本 Vite 的执行 preview 预览时,使用的 proxy 是 server 中的 proxy 配置,官方文档中提供的 preview 的 proxy 无效,这是低版本 Vite 的一个 bug,高版本已经修复,github 上有相关的 issue,也可以通过源码查看。

解决办法:

  1. 在 vite.config.js 使用 server 中的 proxy 代替

  2. 使用 switchhost 进行代理配置

六、解决 Vite 低版本(v2.9以下),unocss 热更新失效:

  1. 解决方法a:升级 Vite,从根本解决问题,以后项目升级比较方便,各种小问题容易规避,推荐升级

  2. 解决方法b:降低 unocss 的版本,可能会出现各种其他问题,不建议

针对这个问题,作者没有降低 unocss 的版本,直接进行 Vite 升级,如果使用 unocss 强烈建议进行 Vite 升级;

不升级后期如果使用其他的依赖包,可能也会有各种其他问题出现

七、解决升级 Vite 项目后,部分依赖包,使用京东镜像无法下载:

产生原因:各种依赖包之间互相依赖,京东镜像的 npm 包可能有问题;

解决方法:非京东私有依赖包,使用 npm 官方镜像下载,京东私有镜像使用京东镜像,初始化项目,生成 package-lock.json 文件,多人合作时,以 package-lock.json 文件为主。

总结:Vite 帮助我们提升开发效率,但是区分 Vite 是否需要使用最新版本,还是需要作为考虑依据:

如果你的项目不使用 unocss,同时对于 preview 下的 proxy 没有特殊要求,那么 Vite2.8.6 + Vue3 + elementPlus 可自动生成预加载文件,省时省力,开发体验好,强烈推荐;如果你的项目使用 unocss 或者对于 preview 下的 proxy 有特殊需求,强烈建议使用最新版本的 Vite,可通过手动配置 optimizeDeps 解决页面刷新的问题。

作者:京东保险 王升升

来源:京东云开发者社区 转载请注明来源

相关推荐
恋猫de小郭6 小时前
Flutter Zero 是什么?它的出现有什么意义?为什么你需要了解下?
android·前端·flutter
崔庆才丨静觅12 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby606113 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了13 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅13 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅13 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅14 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment14 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅14 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊14 小时前
jwt介绍
前端