概述

https://github.com/chalecao/parse_css_in_js

DSL 即「Domain Specific Language」,中文一般译为「领域特定语言」,在《领域特定语言》这本书中它有了一个定义:一种为特定领域设计的,具有受限表达性编程语言。

DSL就是一种特定的语言,如 JSX

AST 即「Abstract syntax tree」,抽象语法树。

抽象语法树是将源代码根据其语法结构,省略一些细节(比如:括号没有生成节点),抽象成树形表达。

通过 https://astexplorer.net/ 这个在线工具,我们可以更直观的查看我们代码生成的AST。

应用:

  • 高级语言的编译
  • 编辑器高亮
  • 前端应用:JavaScript 转译、CSS 预处理、代码压缩、ESLint、Prettier

原理
image.png
image.pngimage.png

Babel 插件原理

image.png

解析->转换->代码生成

整个过程的原理也很简单,首先通过 babylon 这个词法语法分析器,生成 AST。将代码转换成按照特定语法组成的词汇 token 流集合,然后通过 traverse 遍历这个抽象语法树,通过对各个 token 处理,可以转换成需要的语法,比如将=>箭头函数转换成 function,将 let 转换成 var;最后通过 generator 生成符合规范的代码。

  1. const fs = require("fs");
  2. const parser = require("@babel/parser");
  3. const traverse = require("@babel/traverse").default;
  4. const { transformFromAst } = require("@babel/core");
  5. module.exports = {
  6. getAST: (path) => {
  7. const content = fs.readFileSync(path, "utf-8");
  8. return parser.parse(content, {
  9. sourceType: "module",
  10. });
  11. },
  12. getDependencis: (ast) => {
  13. const dependencies = [];
  14. traverse(ast, {
  15. ImportDeclaration: ({ node }) => {
  16. dependencies.push(node.source.value);
  17. },
  18. });
  19. return dependencies;
  20. },
  21. transform: (ast) => {
  22. const { code } = transformFromAst(ast, null, {
  23. presets: ["@babel/preset-env"],
  24. });
  25. return code;
  26. },
  27. };
  • @babel/parser: 转化为 AST 抽象语法树
  • @babel/traverse:对AST进行递归遍历
  • @babel/types:对具体的AST节点进行进行增、删、改、查;
  • @babel/generator:将修改后的AST生成新的代码

    @babel/parser(之前就是babylon)是从acorn fork 出来的

关于如何写babel插件可以参考这里:https://github.com/jamiebuilds/babel-handbook

关于JSX 插件可以看这里:transform-react-jsx 插件的执行阶段是在 babel-traverse 阶段,通过访问者模式,可以访问到抽象语法树的各个节点,JSX 插件主要工作是找到 HTML 片段,将 HTML 转换成一个个具有层级嵌套关系的Virtual Node构成的virtual DOM,准确的说是一个vnode函数。这个函数的参数是元素类型,元素的属性和子元素。



blog/JavaScript抽象语法树AST.md at master · yacan8/blog