Rollup, Vite, Webpack 有什么联系和区别?

  • 三者分别都是前端项目的打包和构建工具。
  • Rollup 用于构建 JavaScript 库,目标是尽可能小和快地构建,提倡使用 ESM 进行模块化开发,热门项目主要是通用性框架:React,Vue,Vuex 和 Vue-Router。
  • Webpack 通常用于复杂项目的打包,有更强的代码拆分能力,热门项目主要是组件库:Element-Plus,Mint-UI。
  • Vite 是现代化的开发服务器,特点在于开发模式下不用打包操作,提供极快的模块热更新和启动速度,生产模式的打包过程基于 rollup 实现。

rollup打包产物解析及原理(对比webpack) - 掘金 (juejin.cn)

在打包的过程中,Webpack 和 Rollup 的具体差异体现在:

  1. Webpack 为了更好地兼容性注入的代码比较多,Rollup 比较干净。
  2. Rollup 诞生于 ESM 标准出来后,原生不支持 CJS,所以可以做到更精准地打包。
  3. Webpack 诞生地更早,所以社区开发地插件更加完善。

Vue 3 使用 Proxy 替换 Object.defineProperty() 的好处?

  1. Object.defineProperty() 不能直接监听数组长度的变化和对象属性的新增或删除,Vue 2 额外提供了 Vue.setVue.delete 方法来触发这种情况下的视图的更新。而 Proxy 原生就可以支持,不需要额外的兼容。
  2. Proxy 可以直接拦截 Map, Set 等集合的操作,Object.defineProperty 则不行。
  3. Object.defineProperty() 需要递归遍历对象的每个属性不同,Proxy 可以懒观察属性,只有在属性被访问时才将其转换为响应式。这大大减少了初始化响应式数据的时间。

Vue 和 React 的 Diff 算法有什么联系和区别?

聊一聊Diff算法(React、Vue2.x、Vue3.x) - 知乎 (zhihu.com)

最朴实的 diff 是 N 个节点去对比 N 个节点,复杂度是 O(N^2)
基于两个基本原则对 diff 过程进行优化:

  1. 节点几乎不会跨层级移动
  2. 同一层级的子节点有 id 作为唯一标识符。

React 的 diff 优化

  1. Tree Diff(整棵树):只对同层级的虚拟 DOM 进行对比,跨层级的操作会删除原节点,创建新节点。
  2. Component Diff(两个组件,例如 <MyComp />):类型相同时,优先对比 Virtual DOM 树,其次根据 shouldComponentUpdate 来判断。
  3. Element Diff(同层级的两个节点,例如 div):
  • 通过 key 来遍历新旧集合,判断是否需要创建和删除
  • 只在 newIndex < oldIndex 的时候才会进行移动。

为什么 element diff 的时候只能前移?
避免不同节点的前移和后移抵消;

Vue 2 的双端对比

  1. 初始化指针:设置 4 个指针,指向旧节点和新节点 list 的首尾。
  2. 循环比较:
  • 首尾比较:先比较两个 首节点,然后比较两个 尾节点。如果节点相同(key 相同),就直接更新节点,并移动指针。
  • 交叉比较:如果首尾没有找到相同节点,就进行交叉比较,比较旧列表的 首节点 和新列表的 尾节点,以及旧列表的 尾节点 和新列表的 首节点。如果相同,移动并更新节点,移动指针。
  • 创建新节点:如果上述都没有找到相同的节点,就在旧列表中找和新列表首节点相同的节点。如果找到了,就移动对应节点。否则就创建新的 DOM。
  • 更新完节点之后,移动指针,进入下一轮。
  1. 添加剩余节点:如果新列表的指针没有走完,说明后剩下的都是新增的节点。
  2. 移除多余节点:如果旧列表的指针还没有走完,说明多余的都是待删除的多余节点。

Vue 3

Vue 3 中针对标注了 key 的元素,还是保留了旧版的双端对比操作。
除此之外,还新增了许多额外的优化:

  1. 在编译阶段标注 hoist 静态节点,并且将多个静态节点用 innerHTML 的方式进行 render,以此减少不必要的对比和重渲染。
  2. 引入 FragmentBlock 的概念,允许单个组件拥有多个根节点,追踪动态的节点。
  3. 编译过程中,对节点的类型进行标注,利用位运算标注 PatchFlag,限制 diff 过程中判断是否更新的操作。