Skip to content

2. 框架设计的核心要素

2.1 提升用户的开发体验

  1. 提供友好的警告信息
  2. 打印的时候让输出的信息更友好
js
const count = ref(0);
console.log(count); // Ref<0>

2.2 控制框架代码的体积

在开发环境中为用户提供友好的警告信息的同时,不会增加生产环境代码的体积

js
// 通过 rollup.js 预定义 __DEV__ 常量,当 Vue 构建开发资源时,会把 __DEV__ 常量设置为 true
if (__DEV__ && !res) {
  warn(
    `Failed to mount app: mount target selector "${container}" returned null.`
  );
}

2.3 框架要做到良好的 Tree-Shaking

概念:消除那些永远不会被执行的代码,也就是排除 dead code

  • 想要实现 Tree-Shaking,模块必须是 ES Module ​,因为 Tree-Shaking 依赖 ESM 的静态结构。
  • 如果一个函数调用会产生副作用,那么打包工具就不会将其移除。但框架可以使用 /*#__PURE__*/ 注释明确告诉打包工具移除该函数,
  • 该注释不仅仅作用于函数,也可以应用于任何语句上。该注释也不是只有 rollup.js 才能识别,webpack 以及压缩工具(如 terser)都能识别它

2.4 框架应该输出怎样的构建产物

vue.global.js 用于开发环境,它包含必要的警告信息,而 vue.global.prod.js 用于生产环境,不包含警告信息

不同类型的产物一定有对应的需求背景,因此需要从需求出发

js
// rollup.config.js
const config = {
  input: "input.js",
  output: {
    file: "output.js",
    format: "iife", // 指定模块形式 // es cjs umd
  },
};

export default config;

无论是 rollup.js 还是 webpack,在寻找资源时,如果 package.json 中存在 module 字段,那么会优先使用 module 字段指向的资源来代替 main 字段指向的资源

2.5 特性开关

  • 对于用户关闭的特性,我们可以利用 Tree-Shaking 机制让其不包含在最终的资源中
  • 该机制为框架设计带来了灵活性,可以通过特性开关任意为框架添加新的特性,而不用担心资源体积变大
js
// example
// webpack.DefinePlugin 插件配置
new webpack.DefinePlugin({
  __VUE_OPTIONS_API__: JSON.stringify(true), // 开启特性
});

2.6  错误处理

框架错误处理机制的好坏直接决定了用户应用程序的健壮性,还决定了用户开发时处理错误的心智负担

Vue.js 错误处理的原理

js
// utils.js
let handleError = null;
export default {
  foo(fn) {
    callWithErrorHandling(fn);
  },
  // 用户可以调用该函数注册统一的错误处理函数
  registerErrorHandler(fn) {
    handleError = fn;
  },
};
function callWithErrorHandling(fn) {
  try {
    fn && fn();
  } catch (e) {
    // 将捕获到的错误传递给用户的错误处理程序
    handleError(e);
  }
}

// 使用
import utils from "utils.js";
// 注册错误处理程序
utils.registerErrorHandler((e) => {
  console.log(e);
});
utils.foo(() => {
  /*...*/
});

2.7  良好的 TypeScript 类型支持

  • 使用 TS 的好处有很多,如代码即文档、编辑器自动提示、一定程度上能够避免低级 bug、代码的可维护性更强等
  • 使用 TS 编写代码与对 TS 类型支持友好是两件事

上次更新于: