【babel】如何实现一个babel plugin

184 阅读1分钟

最近在学zxg_神说要有光的babel通关秘籍

首先推荐一个非常有用的网站

astexplorer

这个网站能我们实现一个plugin 以及AST的分类图能给我们写插件提供帮助

image.png

无非是对各个AST节点进行逻辑处理,实现我们想要的功能

举例,比如我们要实现自动生成文档

/**
 * say 你好
 * @param name 名字
 */
 function sayHi (name: string, age: number, a: boolean):string {
  console.log(`hi, ${name}`);
  return `hi, ${name}`;
}

期望得到

image.png

我们把这段逻辑复制到astexplorer

image.png

可以得知我们处理FunctionDeclaration,它有两个重要的参数

// path 获取节点的信息
// state 节点的状态
  FunctionDeclaration(path, state)

image.png

  • 获取函数名字path.get("id").toString()
  • 获取函数的入参path.get("params")
  • 获取函数的返回类型path.get("returnType").getTypeAnnotation()
// 函数的形式
const { declare } = require("@babel/helper-plugin-utils");
const doctrine = require("doctrine");
const fse = require("fs-extra");
const path = require("path");
const renderer = require("./renderer");

const autoDocumentPlugin = declare((api, options, dirname) => {
  api.assertVersion(7);

  return {
    pre(file) {  // 初始化插件返回的信息
      file.set("docs", []);
    },
    visitor: {
      FunctionDeclaration(path, state) {
        const docs = state.file.get("docs");
        docs.push({
          type: "function",
          name: path.get("id").toString(), // 获取函数名
          // 获取函数的参数
          params: path.get("params").map((paramPath) => {
            return {
              name: paramPath.toString(),
              // paramPath.getTypeAnnotation() 参数的类型
              type: resolveType(paramPath.getTypeAnnotation()),
            };
          }),
          //  返回参数的类型
          return: resolveType(path.get("returnType").getTypeAnnotation()),
          doc:
            // 注释信息单独处理
            path.node.leadingComments &&
            parseComment(path.node.leadingComments[0].value),
        });
        state.file.set("docs", docs);
        },
   
    },
    post(file) {   //  最后返回结果的处理
      const docs = file.get("docs");
      const res = generate(docs, options.format);
      fse.ensureDirSync(options.outputDir);
      fse.writeFileSync(
        path.join(options.outputDir, "docs" + res.ext),
        res.content
      );
    },
  };
});

module.exports = autoDocumentPlugin;

注释的处理 使用doctrine


//  处理注释信息
function parseComment(commentStr) {
 if (!commentStr) {
   return;
 }
 return doctrine.parse(commentStr, {
   unwrap: true,
 });
}

思考:实际工作中需要写一个plugin插件不