写在前面的
对 Vditor 的源码不会进行逐行分析,分析仅限于处理对 Vditor 分析解耦的操作,Vditor 内部代码耦合程度比较高。Vditor Plugin 在不断阅读 Vditor 源码的过程中,不断试图提供更多的开放特性,面临的挑战和设计思路将以博客的形式进行分享。
一个新的目标
抽离 Vditor 自带的特性。需要注意的是,这里需要区分 Vditor 支持的自定义 renderer 和内部支持的特性(下面以 features 进行区分)。Vditor 通过 abcjs、mermaidjs、graphviz、KaTeX 等支持了很多的特性,代码结构十分类似。那么如何将这部分代码统一风格,甚至分离出 Vditor 项目本身呢?这也让我进一步思考如何进行生命周期设计和支持开发者通过 Vditor Plugin 自定义自己的 features~
通过抽离 Vditor 自带的特性实现,可以进一步减小 Vditor 项目本身的体积。
Features 源码分析
Vditor 支持的特性,其源码位于 vditor/src/ts/markdown at master · Vanessa219/vditor (github.com) 其中 xxxRender
的部分。
抽象来说,Vditor 的特性支持是如下的过程:
那么,此过程可以抽象,甚至进一步抽离吗?
我觉得是可以的,如果要实现自定义 features,需要先掌握自定义 renderers 的实现。在此就不赘述自定义 renderers 如何进行实现,这个 API 是由 Lute 提供的,实现方式其实与 Lute 实现自定义渲染器相同。自定义 renderers 实现的环节是 Markdown->HTML,但是自定义 features 实现的过程其实是对生成有特定 attributes 的 DOM 节点的二次渲染。
所以如果要实现相同的效果,在 Lute 不支持的语言的情况下,需要先自定义 renderers,以实现提供特定的 attributes 特征。然后在 HTML 渲染完成之后,再提取这些有特征的 DOM 节点进行三方包渲染。这么来看,Vditor 导出 HTML 是仅完成了第一步,第二步是依赖浏览器环境进行实现的。
至此,Vditor 添加运行时环境,其渲染过程将进一步细化。
性能优化思考
现有的源码实现调用了 Vditor 工具函数 addScript()
,了解 React 设计的同学都知道 this.state
拿到的状态不是实时的,因为 this.setSate({})
的异步实现进一步减少对 DOM 更改的频率。
addScript()
的合并添加似乎是一个性能优化的方向。或者说,在加载插件的前期就预请求静态资源。为了不耽误特性的渲染,可以设置特定的 Promise 队列,预先提取插件的配置加入队列进行请求。对于 addStyle()
工具函数也同样是如此,应该可以实现进一步插件化 Vditor 项目,同时为开发者提供更多开放的可能性。
根据滚动条监听页面 DOM 按需加载,也同样是进一步性能优化的方向,在此就不赘述了。
什么时候开发 renderers?又什么时候开发 features 呢?
features 其实是对 renderers 功能掣肘情况下的进一步补充。features 支持是强依赖 renderers 的结果的,无论 renderers 渲染出的 DOM 节点特征 attributes 是由 Lute 提供的,抑或是自己写渲染器实现的。
引入编译时和运行时的理解,即是 renderers 解决了 Markdown->HTML 的编译过程,而 features 解决了 HTML -> JavaScript 特性渲染 的运行时渲染过程。
那如果引用的第三方包是通过输出 HTML + CSS 进行渲染的呢?
那只写 renderers 则足矣了。
进一步思考发展趋势
Vditor 目前作为一个独立包进行发布。如果有可能的话,对于通用的代码我还是希望独立分包发布。以 Vditor 为核心建立 源码 + 文档 + 插件 + 衍生项目 的完整生态体系,这样可以进一步扩大 Vditor 项目的开源影响力。
为了适配现有 Vditor 源码,对于 3.x 的更新着重于项目源码本身的优化,诸如优化冗余代码、迁移代码风格工具、Sass 迁移 Less 面向未来对样式表开发进一步优化等。。
Vditor@next
着重关注运行时设计,与 3.x 并不完全兼容。在保留现有特性的前提下,对代码执行流程进行进一步优化,希望可以进一步提升无论是用户还是开发者的体验。
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于