Skip to content

在设计框架时,框架会给用户提供诸多特性(或功能),例如我们提供 A、B、C 三个特性给用户,同时还提供了 a、b、c 三个对应的特性开关, 用户可以通过设置 a、b、c 为 true 或 false 来代表开启或关闭对应的特性,这将会带来很多益处。

  • 对于用户关闭的特性,我们可以利用 Tree-Shaking 机制让其不包含在最终的资源中。

  • 该机制为框架设计带来了灵活性,可以通过特性开关任意为框架添加新的特性,而不用担心资源体积变大。 同时,当框架升级时,我们也可以通过特性开关来支持遗留 API,这样新用户可以选择不使用遗留 API,从而使最终打包的资源体积最小化。

那怎么实现特性开关呢?其实很简单,原理和上文提到的 __DEV__ 常量一样,本质上是利用 rollup.js 的预定义常量插件来实现。 拿 Vue.js 3 源码中的一段 rollup.js 配置来说:

js
{
  __FEATURE_OPTIONS_API__: isBundlerESMBuild ? `__VUE_OPTIONS_API__` : true,
}

其中 __FEATURE_OPTIONS_API__ 类似于 __DEV__。在 Vue.js 3 的源码中搜索,可以找到很多类似于如下代码的判断分支:

js
// support for 2.x options
if (__FEATURE_OPTIONS_API__) {
  currentInstance = instance
  pauseTracking()
  applyOptions(instance, Component)
  resetTracking()
  currentInstance = null
}

当 Vue.js 构建资源时,如果构建的资源是供打包工具使用的(即带有 -bundler 字样的资源)​,那么上面的代码在资源中会变成:

js
// support for 2.x options
if (__VUE_OPTIONS_API__) { // 注意这里
  currentInstance = instance
  pauseTracking()
  applyOptions(instance, Component)
  resetTracking()
  currentInstance = null
}

其中 __VUE_OPTIONS_API__ 是一个特性开关,用户可以通过设置 __VUE_OPTIONS_API__ 预定义常量的值来控制是否要包含这段代码。 通常用户可以使用 webpack.DefinePlugin 插件来实现:

js
// webpack.DefinePlugin 插件配置
new webpack.DefinePlugin({
  __VUE_OPTIONS_API__: JSON.stringify(true) // 开启特性
})

最后详细解释 __VUE_OPTIONS_API__ 开关有什么用。在 Vue.js 2 中,我们编写的组件叫作组件选项 API:

js
export default {
  data() {}, // data 选项
  computed: {}, // computed 选项
  // 其他选项
}

但是在 Vue.js 3 中,推荐使用 Composition API 来编写代码,例如:

js
export default {
 setup() {
   const count = ref(0)
   // 相当于 Vue2 中的 computed 选项
   const doubleCount = computed(() => count.value * 2) 
 }
}

但是为了兼容 Vue.js 2,在 Vue.js 3 中仍然可以使用选项 API 的方式编写代码。但是如果明确知道自己不会使用选项 API, 就可以使用 __VUE_OPTIONS_API__ 开关来关闭该特性,这样在打包的时候 Vue.js 的这部分代码就不会包含在最终的资源中,从而减小资源体积

如有转载或CV请标注本站原文地址