10分钟看完 Vue3 工程适配
1. 开始
本文为 Vue3.x
工程适配记录。项目中很多老工具、组件都是基于 Vue2.x
的,而且还在用,所以基本是戴着镣铐跳舞,需要向下兼容,同时追求高效、简单。
适配大体分两类,运行时和编译时,运行时适配包括各种语法,编译时适配包括 Webpack Loader
、Plugin
、transpileDependencies
等方面。
2. 基础配置
首先基于当前项目架构,搭建了 vite
基础配置。
当前架构是什么?就是形如 src/project/user
的 monorepo
模式。
还有对 devcloud
中 node
版本升级,打包产物位置的更新,等这些比较小的点。
3. 适配
3.1. TIP_PLATFORM_NAME 适配
一个 Vite 插件 即可解决。
但是对于第三方库,需要额外的技巧。
需要在 vite.config.ts
中的 optimizeDepsExcludes
中将其排除,否则在 vite
的依赖分析的时候就会提前报错,此时还没到插件的处理时机。
这样处理后,一些用 commonjs
的三方库可能会报错,这时又需要添加 optimizeDepsIncludes
,让插件处理这些依赖。
3.2. 组件库适配
一些三方库是以源码方式提供的,比如 press-plus
,Vue2.x
时可以配置 transpileDependencies
,但是 Vite
没有对应的配置项。
可以这么处理:
- 将三方库复制到
src
下的某个目录下 - 为三方库配置
alias
,指向src
某目录下 - 配置
tsconfig.json
的compileOptions.paths
除组件库外,一些类似 pmd-tools
的三方库也可以这样处理。需要注意的是,一旦配置 alias
为本地源码后,一些依赖要额外安装(比如 vue-runtime-helpers
),否则在 pnpm
项目中可能找不到。
3.3. 条件编译
项目支持条件编译,一些地方使用它会非常简单。比如 src/component/logic/tip-merchant/jump-handle/helper.js
中 对 configInfo
的适配。
3.4. node.js 版本
node
版本必须 >= 16
,可以使用 nvm
切换,非常方便。
devcolud
已支持。
3.5. template v-for
Vue2.x
和 Vue3.x
的 :key
使用互不兼容,前者不能放到 template
上,后者必须放到 template
上,且是 vscode
插件的报错,不是 eslint
的报错。
一个简单的解决办法就是把 template
改成 div/span
。
参考:https://v3-migration.vuejs.org/zh/breaking-changes/key-attribute.html
3.6. vite 依赖缓存
vite 有依赖缓存,禁用缓存可以用 sudo npm run dev --force
3.7. vite root
修改了 vite.config.ts
中的 root
后,比如设置为 subProject
路径,需要更改 envDir
,否则客户端拿不到环境变量。
3.8. 支持 history 模式
router
需要改成:
vite.config.ts
中增加额外配置,支持上云和 history
模式。
3.9. 其他
还有很多其他小的适配和改造,直接看官方文档就行了。
比如 .sync
的去除,这里我写了脚本对 component
子仓库进行了批量替换,
4. 实例
Vue 中的实例分应用实例和组件实例,Vue2.x
中开发者不用太关心,因为它用了原型链,在组件实例尝试获取应用实例的属性,也可以拿到。Vue3.x
中则不一样。
比如 $ebus
的适配,首先 $ebus
一定是挂载在应用实例上,这样每个组件才能拿到相同的。下面代码是错误的:
并且挂载时机也必须在 mount
之前。下面的代码就是错误的:
贴两张图,直观感受下应用实例和组件示例的差别。应用实例:
组件实例:
5. 总结
好的工程配置可以事半功倍,升级 Vue3 在我看来不只是语法的升级,更重要的是工程的配置。你可以在 Vue3 中写 hooks
,也可以写 options API
,这些都是小事,重要的是你得有这样一套配置,并且对基础组件、基础工具库做好兼容。
复杂的事情简单做,而不是反过来。一天天吭哧吭哧加班,装作很忙的样子,最后代码写的像屎一样。对应到 Vue3 适配,Press 系列组件库、底层工具都是兼容 Vue3 的,所以上层改动很少,如果由 KPI 驱动型的人来做,估计又要重新写一套组件库,当作自己辉煌的 KPI 了。
至于 Press 系列组件库是如何兼容 Vue3 的,可以参考之前的文章。