功能介绍
webpack中的发布订阅模式是使用tapable实现的。tapable比node自带的evevnEmitter功能更加强大,表现在1. 一次发布能触发多个订阅钩子; 2. 事件流种类更多,分为bail,basic, loop, waterfall。当然,学习难度也更高。我开发这个工具的目的是想将tabable代码转换成流程图,更直观的了解对应的tabable执行流程。
思路:
1. 获取左侧代码片段
2. 将代码片段经过ast语法树解析,解析出使用的tapable钩子
3. 针对不同的钩子渲染不同的流程图
有了思路我变开始选择使用的库:
- mxGraph: 绘制流程图
- esprima + estraverse: 解析分析代码
- monaco-editor:代码编辑器
- Umi:基础框架
当初设想的以为很简单,但是实现起来发现用到的每个库挺大,有一定的学习难度。所以这个项目是试水项目,我也算基本对这几个库入了门,后期有需要再进行深入学习。
页面地址:tapable可视化工具
github地址:tapableUtil
编辑器(monaco-editor )
核心代码:
// 1. 初始化编辑器
let monacoInstance = monaco.editor.create(document.getElementById('editor'), {
theme: 'vs-dark',
scrollBeyondLastLine: false,
value: '代码片段',
language: 'javascript',
})
// 2. 获取代码片段
let code = monacoInstance.getValue()
需要注意的坑:
代码中如果只引入monaco-editor 会发现界面是出来了,但是没有语法高亮。在控制台输入monaco.languages.getLanguages()
发现根本没有javascript语法,只有一个最基础的plaintext。
此处有两种解决方案:
1. 代码中引入monaco自身提供的javascript内置语言
import 'monaco-editor/esm/vs/basic-languages/javascript/javascript.contribution';
2. 修改webpack配置,如果使用的是umi,也可以按照umi官网有提供配置方法(monaco-editor 编辑器打包)。
PS. umi的webapck配置文件需在根目录下新建config/config.js文件。
代码解析(esprima + estraverse)
esprima: 一个强大的库,将js代码转ast语法树
estraverse: 提供遍历ast语法树的钩子
astexplore: 提供可视化的代码片段转ast语法树网站,遍历ast语法树时对应此网站的结构能更方便的知道自己想获取的节点结构
核心代码:
// 代码转ast
let ast = esprima.parse(code)
// 遍历ast语法树
estraverse.traverse(ast, {
enter(node) {
// xxx 具体代码
}
})
具体的代码可以参考esprima和estraverse的官方文档,此处不再具体介绍。在遍历语法树时,可以根据astexplorer这个网页展示的语法树结构进行遍历。
图像渲染(mxGraph)
核心代码:
var graph = new mxGraph(container)
// 清空画布
graph.removeCells(graph.getChildVertices(graph.getDefaultParent()))
// 开始绘制
graph.getModel().beginUpdate()
// 绘制图形
var cell = graph.insertVertex(parent, 0, tap, x, y, w, h)
// 绘制cell 和 step之间的连线
graph.insertEdge(parent, null, '', cell, step)
需要注意的点:
1. 交互上涉及到点击按钮后重新绘制流程图,所以需要在重新绘制前清空图层中的单元。否则会出现新的图块和旧图块混在一起的情况。
graph.removeCells(graph.getChildVertices(graph.getDefaultParent()))
2. 连线时为了避免①和②两条线黏连在一起,设置了线上的点的位置
var line = graph.insertEdge( parent, null,'false',step,end)
// 固定线经过的点的位置
line.geometry.points = [new mxPoint(pointX, pointY)]