# 命令式和声明式
命令式
- 关注过程
- 性能佳
- 不易维护(
维护实现过程因而心智负担大
)
声明式
- 关注结果
- 性能
不优于
命令式编程 - 易维护
====》框架要做的
框架封装了命令式代码
从而实现了面向程序员的声明式,从而使的程序更易于维护扩展
如果更新一段代码,命令式的性能消耗为命令式更新A,对应声明式的新能消耗为找出差异B + 命令式更新A,从而一个优秀的框架要做的就是让声明式代码逼近命令式代码
的性能,重点在于缩小找出差异
的性能开销
====》最小化找出差异
的性能开销的过程中探索出了 虚拟dom
方案
# 虚拟dom
虽然理论上性能不高于原生dom操作,但是很难写出并维护最优的命令式代码
- (一般而言)创建时性能开销并不优于原生操作,甚至更差(源于创建真实dom的同时还有创建对应VNode结点的性能开销)
- 纯js层面操作比dom操作快很多,不在一个数量级,因此在更新时原生操作性能开销(一般而言,特别是针对innerHtml操作)远大于虚拟dom
- 理论上性能弱于极致优化的原生js(能做到原子级别的更新),但在保证心智负担和可维护性上性能还不错
# 运行时和编译时
运行时
- 无法分析用户输入内容进而做编译优化
编译时
- 灵活性不足,用户输入内容必须编译后才能使用
# 如何刚好的设计面向用户的框架
提升开发体验
- 清晰丰富的
warning
信息 - 直观的数据打印,如借助
chrome
浏览器DevTools
的formatter
(Vue中的initCustomFormatter)
控制代码体积
- 使用开关(Vue中的__DEV__)控制打包出的版本,如一些
warning
信息可不包含在生产环境包(.prod.js)中
良好的Tree-Shaking
- 模块必须是
ESM
(ES Module),Tree-Shaking
依赖ESM
静态结构 Tree-Shaking
只会筛掉dead code
,不会筛掉产生副作用的函数,因而要擅于使用无副作用声明机制,如rollup中的/*#__PURE__*/
注释
框架的输出产物
- 为了支持浏览器端
<script>
标签引入,打包产物应为IIFE
,在rollup
中配置format: iife
- 在浏览器支持
ESM
情形下,在rollup
中需要配置为format: esm
- 为了支持node,打包产物应为
cjs
模块资源,在rollup
中需要配置format: cjs
-bundler.js
一般为打包工具使用资源,-browser.js
一般为提供给浏览器使用资源,区别在于特性开关的控制,其中打包工具一般使用process.env.NODE_ENV === 'production'
来判断所处环境,而特性开关由开发者控制
特性开关
- 一般以下划线链接大写字母命名,如
vue
中__DEV__
错误处理
- 统一的错误处理函数,如
vue
中的registerErrorHandler
函数(思考所采用的设计模式)
Typescript类型支持