升级到 Vue 3
2022年8月16日 · 263 字 · 2 分钟 · Vue Vue3 Framework Legacy
原文地址:https://jaufey.notion.site/Vue-3-48f24aab000244dfb4583c7948221a24
上周末花了一些时间把手头的一个小项目从 Vue 2.6 升级到 Vue 3.2,把 webpack 从 2 点多升到了 5。本篇文章记录一下过程。
迁移原因
- 心理原因:这个小项目的模板是从一个旧的 monorepo 的项目脱胎出来的,webpack 的配置有些杂乱有些绕,属于能跑就行。改不太动,索性升级,不然这块内容对我来说永远是技术债,是不想去触摸的一团模糊。
- 直接原因:想给应用加一个 Notification 的功能,这个功能需要 https 环境。 但是 webpack-dev-server 的 https 配不成功,开启 https 后一访问服务就崩溃。
- 其他原因:积累经验
迁移目标
- 原先的项目能跑
- 原先的 webpack 配置,觉得有用的,在迁移后要保留下来
- 在迁移后,能够通过阅读 webpack 文档
- 自由地测试各提供方的 Loader 和 Plugin
- 自由地测试 webpack 的新功能
- 将来可从工具链角度优化项目性能,使其不再是一团模糊
- 进阶:以 webpack 为抓手,扩展了解不同构建工具:gulp, babel, parcel, snowpack,esbuild,vite,swc。(这些名次对我来说很眼熟,但只在初学 HTML 时接触过 parcel,所以不好意思有可能把不同类型的东西并列在了一起)
迁移了哪些内容
在迁移之前,首先是过了一下这个里面提到 https://v3-migration.vuejs.org/ 的问题。
因为首次完整通读了的文档版本就是 Vue 3 的,所以不会心怯,也不需要再读一遍了。
(这是基于初识 Vue 3 所练手的一个小东西:Github)
迁移目标的第一点决定了我几乎只记录 breaking change。
- 项目上的改动:
- Vue 的 protoType 上面不能绑东西了,如果仍需在组件内使用公共方法,则需要在 Vue instance 的 globalProperties 上绑。(迁移文档中有)
- $set 和 $delete 不存在了。Vue 3 的响应式基于 proxy,可放心地给 Object 增删属性。(迁移文档中有)
- 原生支持 teleport 内置组件(基本文档中有)
- 所以之前封装的模态框组件不再需要手动挂载到全局上,转而使用 teleport 包装。
- 文档中没有提到的变动:在在子组件中使用 $parent 时,Vue 2 不会获取到自定义组件的实例,会跳过。但在 Vue3 中 transition/teleport 等内置组件都会作为组件实例被 $parent 获取到。导致我的一些很拉的代码无法 work 了:
- 在原先的实现中,模态框组件中的 slot 内容想要关闭模态框时,会调用 $parent.closeModal 函数来实现目标。
- 但升级以后 $parent 获取不到正确的模态框组件实例,所以就会出问题。
- 怎么解决的呢?外层模态框 provide closeModal 方法,内部 slot 内容组件 inject closeModal 方法,但这是不负责任的飞线做法。正确的做法参考(https://stackoverflow.com/questions/50942544/emit-event-from-content-in-slot-to-parent,改天还需要熟悉一下 slot 的作用域)
- 生命周期钩子函数名字变动:(迁移文档中有)
- 组件生命周期:beforeDestroy,destroyed 等改为 mount 所对应的字眼
- 自定义指令生命周期:inserted, update 等变动
- 模板中的 filter 被移除。以后都建议使用 computed 来实现相同的效果。(迁移文档中有)
- new Vue 改为 createApp(迁移文档中有)
- 事件及事件触发的对象改变。不需要 .native 去获取原生事件了(迁移文档中有)。在 Vue 2 开发时踩过这个坑
- 组件双向绑定变了。Vue 3 弃用 value+input 的组合,默认为 modelValue+update:modelValue,还可多值双向绑定了。(迁移文档中有)
- 在 router-view 标签内如果添加了(loading)内容,则路由所对应的组件内容将不会被渲染。(迁移文档中无)
- 注释放到模板内容第一行的话,$el 的值就是错误的(迁移文档中无)
- 依赖上的改动
- vuex, vue router 升级,但项目没有用到什么新东西
- 一些普通的运行时依赖:
- 如果还能用,没有报错,就没有升级
- 对 Vue2 和 Vue3 区分了不同版本的依赖
- 如 vue-toastification 则进行了升级
- 如 vue-codemirror 报错,其有 Vue3 版本
- 配置方式发生改变,API 接口改变。兼容 Vue 2版本的 vue-codemirror 的配置粒度较细,兼容 Vue 3 版本的 vue-codemirror 提供了一个 basic-setup 启动配置,基本满足需求。像原来的 keymap 如今包含在 basic-setup 中了
- 引入依赖的方式发生改变。现在需要单独安装需要用到的 codemirror extensions。比如 language package 或 theme,有利于摇树、节省体积。
- Vue 3 版本的 vue-codemirror 还待完善,比如 theme 目前只支持一个 one-dark。由此可见虽然 Vue 3 的主生态算是比较完善了,但各依赖对 Vue 3 的适配还在“进行时”,尤其是像 codemirror 这种比较重的东西。
- 工具链上的变动
- Vue 3 对 webpack 的配置进行了比较好的封装,几乎做到了开箱即用。
- 如果有自定义 webpack 配置的需求,则在 vue.config.js 中追加配置即可。
- 简单的基础配置
- 链式调用 webpack chain。在达到迁移目标的第3点的过程中需要多了解。
迁移目标完成情况
- (完成)原先的项目能跑
- (完成)原先的 webpack 配置,觉得有用的,在迁移后要保留下来
- Vue Cli 流程走下来该有的几乎都有了
- 还缺一个 postcss 未看到效果,待测试安装
- (持续进行)在迁移后,能够通过阅读 webpack 文档调试工具链
下一步计划(一个月以内完成):
- 配置 eslint、postcss
- 学习使用 composition api 语法
- 学习使用 VueUse
以上所描述的迁移内容大都只是按部就班的东西。
下一篇文章,讲下迁移过程中遇到的一个重点问题:static hoisting 及思考