最近在看《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、代码的可维护性更强等等。