- 开始时间:2019-03-01
- 目标主要版本:3.x 版本
- 引用 issue:N/A
- 实现的 PR:N/A
摘要
通过尽可能多地通过命名的导出来暴露 API,使 Vue 运行时具有 tree-shakable。
基本范例
import { nextTick, observable } from 'vue'nextTick(() => {})const obj = observable({})
动机
随着 Vue 的 API 增长,我们一直在努力平衡功能和包大小之间的权衡。我们希望将 Vue 的大小开销保持在最低水平,但是我们也不希望因为大小限制而限制其能力。
有了 ES 模块的静态分析的友好设计,现代 bundlers combined 和 minifiers 相结合,现在可以消除(eliminate) bundler 中任何没有使用 ES 模块导出的地方。我们可以重组 Vue 的全局和内部 API,以利用这一点,使用户只为他们实际使用的功能买单。
此外,由于知道可选功能不会增加不使用这些功能的用户的 bundler 大小,我们现在有更多的空间在核心功能包含可选功能。
具体设计
目前在 2.x 版本,所有的全局 API 都暴露在单个 Vue 对象上:
import Vue from 'vue'Vue.nextTick(() => {})const obj = Vue.observable({})
在 3.x 版本,它们只能作为命名的 import 方式访问:
import Vue, { nextTick, observable } from 'vue'Vue.nextTick // undefinednextTick(() => {})const obj = observable({})
通过不附加在 Vue 上默认导出所有 API,任何未使用的 API 都可以由支持 tree-shakable 的 bundle 产生的最终 bundler 中被丢弃。
受影响的 2.x API
Vue.nextTickVue.observableVue.versionVue.compile(only in full builds)Vue.set(only in compat builds)Vue.delete(only in compat builds)
内置辅助 API
除了公共 API,很多内置组件和 helpers 也可以作为命名的导出物导出。这使得编译器可以输出只在使用的时候才导入的功能代码。例如下面的模版:
<transition><div v-show="ok">hello</div></transition>
可以编译成一下内容(用于解释,不是准确的输出):
import { h, Transition, applyDirectives, vShow } from 'vue'export function render() {return h(Transition, [applyDirectives(h('div', 'hello'), this, [vShow, this.ok])])}
这意味着 transition 组件只在实际用到的时候才会被导入。
请注意,上述内容只适用于 ES 模块构建,用于 tree-shakable 功能的 bundlers 构建仍然包括所有功能,并且 Vue 全局变量上暴露所有内容(并且编译器将产出适当的输出,以使用全局上的 API,而不是导入)。
缺点
用户不能再导入一个单一的 Vue 变量,然后使用它的 API。然而,这应该是一个值得的权衡,因为可以使 bundler 的尺寸最小。
全局 API 在插件中的使用
一些插件可能依赖最初在 Vue 上公开的全局 API:
const plugin = {install: Vue => {Vue.nextTick(() => {// ...})}}
在 Vue3.0 中,它们需要明确地导入这些东西:
import { nextTick } from 'vue'const plugin = {install: app => {nextTick(() => {// ...})}}
这产生了一些开销(overhead),因为它要求库的作者在他们的构建设置中正确配置 Vue 的外部化:
- Vue 不应该绑定在库中;
- 对于模块构建,import 应该被搁置,由最终的用户 bundler 来处理;
- 对于 UMD 或者浏览器构建,应该先尝试全局的 Vue.h,然后回到 require 调用。
这是 React 库中常见的做法,webpack 和 Rollup 都可以做到这一点。相当数量的 Vue 库也已经做到了。我们只需要提供适当的文档和工具支持。
备选方案
N/A
采纳策略
作为迁移工具的一部分,应该可以提供一个代码 mod。
没有解决的问题
N/A
