使用AST快速解决css代码重构问题

抽象语法树(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端能用的文件。

最小化代码(也可以下载本文末尾附件,安装依赖后执行node app.js)

/**
 * 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()