框架设计的核心要素|Vue.js 设计与实现

266 阅读3分钟

最近在看《Vue.js设计与实现》(HcySunYang) 这本书。粗略的看了一遍,学习到了很多。从框架的设计到不同模块的实现,思路讲的很清楚,真的做到了深入浅出。接下来会写几篇文章来记录总结一下。

  • 提升用户的开发体验
    • 提供友好的警告信息。提示状态+原因。让用户能够清晰且快速的定位问题。
  • 控制框架代码的体积
    • 体积越小,最后浏览器加载资源的时间也就越少。
    • 思考:提供友好的提示就意味着需要编写更多的代码,体积也就会越大。这个问题的解决办法就是,区分开发和生产环境。Vue3 使用的方式是,使用 rollup 的插件配置来预定义 __DEV__ 变量。当 Vue.js 在输出资源的时候,会输出两个版本,一个用于开发,一个用于生产环境。生成前者时,会把 __DEV__ 设置为 true,而后者则设置为 false
  • 框架要做到良好的 Tree-Shaking
    • 如何做到呢?
    • 首先,这个概念因 rollup.js 而普及。简单的说,Tree-Shaking 指的是消除那些永远不会被执行的代码。现在无论是 rollup 还是 webpack 都支持 Tree-Shaking。
    • 其次,想要实现 Tree-Shaking,必须满足一个条件,即模块必须是 ESM。因为 Tree-Shaking 依赖 ESM 的静态结构。
  • 框架应该输出怎样的构建产物?
    • 不同类型的产物一定有对应的需求背景。因此需要从用户需求讲起。以 Vue.js 为例:
    • 用户希望可以直接在 <script> 标签引入框架并使用。为了实现这一需求,我们需要输出一种叫 IIFE 格式的资源。实际上,vue.global.js 文件就是 IIFE 形式的资源。
      <body>
        <script src="/path/to/vue.js"></script>
      
        <script>
          const { createApp } = Vue;
          //...
        </script>
      </body>
      
    • 不过,随着技术的发展和浏览器的支持,现在主流浏览器对原生 ESM 的支持都不错,所以用户除了能够使用 <script> 标签引用 IIFE 格式的资源外,还可以直接引入 ESM 格式的资源,例如 Vue3 还会输出 vue.esm-browser.js 文件。用户可以直接用 <script type="module"> 标签引入。
  • 特性开关
    • 为特性提供开关。关闭的特性可以通过 Tree-Shaking 机制删除,同时也为框架带来的灵活性,框架升级时可以通过特性开关来支持遗留 API。
  • 错误处理
    • 框架错误处理机制的好坏直接决定了用户应用程序的健壮性,还决定了用户开发时处理错误的心智负担。
    • 对错误机制进行封装。为用户提供统一的错误处理接口。
    • 错误处理的能力完全由用户控制。用户既可以选择忽略,也可以调用上报程序将错误上报给监控系统。
      // 内部定义
      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(() => {...});
      
  • 良好的 TypeScript 类型支持
    • 使用 TS 好处很多:代码即文档、编译器自动提示、一定程序上避免低级 bug、代码的可维护性更强等等。