本期作者:陈圆 openInula社区架构SIG成员
《openInula茶话会》专栏每周不定期分享业务知识、实战经验与开发技巧,帮助社区成员快速提升技能,开启技术探索之旅! 本期介绍《Vue转换到openInula技术揭秘》,欢迎查阅。
项目背景
openInula问世以来吸引众多产品从React框架平滑切换到openInula框架,截止目前openInula已经支撑千万级代码规模商用。同时,不少产品提出帮助产品从Vue框架切换到openInula框架的诉求。因此openInula社区提供了一个转换工具,帮助产品从Vue框架切换到openInula框架。
整体方案设计
整体方案分3个部分:
- Vue代码转换工具:转换工具负责将Vue文件转换成jsx文件,涉及到模版转换、JS转换和css转换。
- Vue API适配层:适配层提供Vue API到openInula及生态的API 适配层,以便转换工具进行API转换。
- UI组件库:提供组件库适配层,将Vue框架的ElementUI组件库转换到openInula框架组件库。
Vue To openInula转换工具
转换工具主要分成3部分: 模版转换、JS转换和CSS转换。下面分别介绍这3部分转换原理。
模版转换
- 读取Vue文件,利用@vue/compiler-sfc提供的parse对模版进行解析,解析后的数据通过自定义lintTemplate进行简单格式预处理
javascript
const sourceStr = fs.readFileSync(srcPath, 'utf8');
// 解析 .vue 文件,获取解析结果
const parsed = parse(sourceStr);
const template = await lintTemplate(parsed.descriptor.template?.content);
- 使用@babel/parser将模版文件字符串编译成ast语法树
javascript
import parser from '@babel/parser';
const templateAst = parser.parse(targetTemplate, {
sourceType: 'module',
allowTemplateLiterals: true,
plugins: ['jsx'],
});
- 遍历ast语法树,根据需要处理每一个节点元素、属性绑定、事件等,这里就可以将v-if、v-for、v-show、v-modal等Vue模版语法转换成openInula的jsx语法。
javascript
traverse(templateAst, {
JSXElement(path) {
// 处理元素节点
},
JSXAttribute(path) {
// 处理属性
}
JSXExpressionContainer(path) {
// 表达式处理
}
// 其他
});
JS转换
- 读取Vue文件,将TS语法编译成js语法
- 和模版转换类似,利用@bable/parser将js文件的字符串转成ast语法树
- 区分vue options api和composition api分别进行语法树解析转换,主要完成以下工作
- 处理import,将原本import vue生态组件转成openInula生态组件
- 将Vue生命周期方法转入到openInula生命周期执行
- 将底层变量用useMemo包裹,放在openInula组件中
- 处理国际化等生态组件
- 将Vue中变量赋值进行转换,以适配openInula语法
- 处理Vue中this指针问题下
CSS转换
Vue中存在局部CSS作用域的scoped语法,但是openInula中没有改功能。因此,引入scoped-css-loader在Webpack编译期完成局部CSS的编译。 Vue中的CSS只需转成对应的CSS文件,并将文件名以scoped.css结尾即可完成局部CSS功能。Webpack配置如下
javascript
{
test: /\.less$/,
use: [
MiniCssExtractPlugin.loader,
{
loader: 'css-loader',
},
{
loader: 'postcss-loader',
options: {
postcssOptions: {
plugins: ['postcss-import', 'postcss-nested'],
},
},
},
{
loader: 'less-loader',
},
{
loader: 'scoped-css-loader',
},
],
},
{
test: /\.scss$/,
use: [
MiniCssExtractPlugin.loader,
{
loader: 'css-loader',
},
{
loader: 'postcss-loader',
options: {
postcssOptions: {
plugins: ['postcss-import', 'postcss-nested'],
},
},
},
{
loader: 'sass-loader',
options: {
// 每个项目地址不同
additionalData: '@import "/convert/assets/common/style/common/varible.scss";'
}
},
{
loader: 'scoped-css-loader',
}
],
},
总结
Vue语法灵活性较高,将Vue文件转成openInula涉及细节众多,这里没有详细展开描述,仅介绍了转换流程关键动作。。如果各位开发者感兴趣,欢迎评论或留言,后续文章将展开描述更多细节。
🌈代码仓地址:gitee.com/openinula/i... 💻官网:www.openinula.net/