抽象語法樹(AST)相信很多從事後端開發的同學都已經很瞭解了,得益於nodejs這兩年的發展,很多前端同學也對AST有所研究,像近兩年出現的小程序開發框架wepy mpvue等確實解決了不少前端開發中的實際問題,像mpvue這種框架的原理是什麼,其中比較核心的功能就是使用AST來完成js,html,css的編譯,趁着年初不忙,對去年一個項目中AST的應用做下簡單分享,高手勿噴哈!
先說下需求背景,已經有一些小程序頁面,現在產品要求能在pc管理後臺可視化預覽這些頁面,這裏只介紹其中一個簡單的功能點就是css部分的重構,來幫助大家入門。
小程序使用mpvue開發,pc後臺也是使用vue開發,這樣html模板大部分可以複用,只需替換一些組件,css部分小程序使用sass, 裏面的尺寸單位都是750rpx,但在pc上預覽的時候只有430px,最早使用sass中的一些函數來解決此問題,但發現太費時間,效率不高,最後決定用使用node-sass先將scss轉換css文件, 再使用css做ast轉換的常用庫css-tree把css代碼解析成json樹,調用csstree.walk對想要重構的尺寸,單位進行修改,修改完後調用csstree.generate再生成css代碼,最後部分做成一個命令行工具,對小程序寫好的scss文件直接轉換爲pc端能用的文件。
最小化代碼
/**
* Created by liujinghao on 2018/12/5.
* 基於ast 轉換mpvue項目中的scss文件,使其兼容在pc上顯示
*/
const sass = require('node-sass')
const fs= require('fs')
const csstree = require('css-tree');
let convertCss= function (scssFilePath) {
return new Promise((resolve,reject) => {
sass.render({
file: scssFilePath
},
function (err, result) {
if(err){
reject(err)
}else {
let css = result.css.toString()
resolve(css)
fs.writeFile('out.css', css, function () {
console.log('scss轉換爲css後寫入到out.css')
})
}
})
})
}
let createCode = async function () {
let cssString = await convertCss('diy.scss')
let ast = csstree.parse(cssString)
let copy = csstree.clone(ast);
fs.writeFile('ast.txt', JSON.stringify(ast), function () {
console.log('ast分析代碼寫入到ast.txt')
})
csstree.walk(copy, function (node, item, list) {
//console.log(node.type,'____', node.value)
if (node.type === 'Dimension') {
node.value = (node.value / 1.745).toFixed(3)
console.log(node)
}
});
let transCode = csstree.generate(copy)+''
transCode = transCode.replace(/rpx/g,'px')
// console.log(transCode)
fs.writeFile('transCode.css', transCode, function () {
console.log('最終代碼寫入到transCode.css')
})
}
createCode()