一、概述
在基础架构基于物料的前端技术架构与共建方案中有详细的设计规范,但实际应用中却很难保证所有的地方都按照规范做,比如会出现金额没有统一千分位展示、表格的金额没有统一居右展示、表格内容超出没有省略号展示等这些影响美观度的问题。而我们的项目一般有几百个页面,靠人工检查和测试是很难保证完全符合规范的,因此就只能通过扫描工具去保证。
在阅读之前建议看下Vue源码专栏以及你知道Vue是怎么把Hello World渲染出来的吗?
二、调研
1、当前是否有现成的工具?
无
2、如果自己想实现思路该如何?
首先确定方案是静态扫描还是运行时扫描
运行时扫描: 方案需要有真实或者去MOCK数据,成本过高,决定放弃~
静态扫描:扫描所有的Vue单文件组件,提取模板部分进行分析,该方案实现的核心是提取如何从单文件组件提取模板?
3、静态扫描时如何抽离单文件组件的模板?
(1)、先看下vue项目中的单文件组件是如何编译的?
- 解析:编译器会解析
.vue
文件,将其拆分成三个部分:模板(template)、样式(style)和逻辑(script)。 - 模板编译:模板部分会被编译成渲染函数。Vue 使用了模板编译器将模板转换为渲染函数的过程,这个渲染函数会在组件实例化时被调用,用于生成组件的虚拟 DOM。
- 样式处理:样式部分会根据你的构建配置进行处理。例如,如果你使用了 CSS 预处理器(如 Sass 或 Less),编译器会将样式转换为普通的 CSS 代码。
- 逻辑处理:逻辑部分会被转换为 JavaScript 代码。这部分包含了组件的选项(如 data、methods、computed 等)以及其他的 Vue 相关代码。
- 组件生成:编译器会将模板、样式和逻辑部分合并,并生成一个可执行的 Vue 组件。
其实我们的扫描工具只会用到解析和编译部分,重点是如何将单文件组件拆成模板、样式和逻辑三部分的以及如何获取模板部分,只要获取了模板部分就可以定义规则进行分析了。
(2)、如何拆分单文件组件中的模板
如何看下项目的package.json,会发现所有的Vue项目都会有vue-template-compiler
这个库,它其实就是Vue官方提供的单文件组件编译工具库。 如何使用 vue-template-compiler
抽离 Vue单文件组件中的模板部分呢?
- 安装 & 引入
arduino
npm install vue-template-compiler
js
const { parseComponent } = require('vue-template-compiler');
- 单文件组件的模板代码
ini
// 读取Vue文件
const vueContent = fs.readFileSync(path.resolve(__dirname, '../test/index.vue'), 'utf8');
- 使用
vue-template-compiler
的parseComponent
方法来解析单文件组件的内容,并提取模板部分:
arduino
// 解析Vue文件
const { template } = parseComponent(vueContent);
- 查看扫描文件结果 解析出来的是模板字符串,如下图所示:
4、制定规则进行分析
拿到了模板字符串就可以根据扫描需求制定相应的规则进行分析了,一般要写正则表达式,如下所示:
5、模板字符串的缺点
由于是字符串,一般只能通过写正则表达式来制定规则,但是当遇到复杂的规则时正则表达式的实现复杂度会很高,那有没有更好的方式呢?
三、更好的实现方案之模板结构化
在Vue模板的编译的第二步是将模板编译成渲染函数,其中有一部是生成抽象语法树(AST),那能不能利用抽象语法树呢?
1、如何将模板文件转成抽象语法树
@vue/compiler-dom
是 Vue.js 提供的一个包,用于在构建工具或者其他环境中编译 Vue 单文件组件的模板部分。它是 Vue 模板编译器的一部分,提供了一组功能强大的 API 来处理和编译 Vue 模板。
php
// 引入@vue/compiler-dom库
const { compile } = require('@vue/compiler-dom');
// 将获取的模板编译ast
const ast = compile(template.content, {
mode: 'module',
}).ast;
2、如何使用AST实现规则的编写
以下是实现的扫描表格中金额列是否千分位展示以及右对齐
3、测试结果
源码中不符合规则的地方:


扫描结果71行和88行不符合规范:

四、总结
目前扫描工具是融合在cli工具上的,如果需要增加规则需要频繁发版,后续可以把规则放到外面以插件的形式提供,每个项目单独配置开发。