# 命令式和声明式

命令式

  • 关注过程
  • 性能佳
  • 不易维护(维护实现过程因而心智负担大

声明式

  • 关注结果
  • 性能不优于命令式编程
  • 易维护

====》框架要做的 框架封装了命令式代码从而实现了面向程序员的声明式,从而使的程序更易于维护扩展 如果更新一段代码,命令式的性能消耗为命令式更新A,对应声明式的新能消耗为找出差异B + 命令式更新A,从而一个优秀的框架要做的就是让声明式代码逼近命令式代码的性能,重点在于缩小找出差异的性能开销

====》最小化找出差异的性能开销的过程中探索出了 虚拟dom 方案

# 虚拟dom

虽然理论上性能不高于原生dom操作,但是很难写出并维护最优的命令式代码

  • (一般而言)创建时性能开销并不优于原生操作,甚至更差(源于创建真实dom的同时还有创建对应VNode结点的性能开销)
  • 纯js层面操作比dom操作快很多,不在一个数量级,因此在更新时原生操作性能开销(一般而言,特别是针对innerHtml操作)远大于虚拟dom
  • 理论上性能弱于极致优化的原生js(能做到原子级别的更新),但在保证心智负担和可维护性上性能还不错

# 运行时和编译时

运行时

  • 无法分析用户输入内容进而做编译优化

编译时

  • 灵活性不足,用户输入内容必须编译后才能使用

# 如何刚好的设计面向用户的框架

提升开发体验

  • 清晰丰富的warning信息
  • 直观的数据打印,如借助chrome浏览器DevToolsformatter(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类型支持