如何使用Babel向该文件添加导入

时间:2016-03-10 19:43:47

标签: babeljs

假设您有一个文件:

AddReactImport();

插件:

export default function ({types: t }) {
  return {
    visitor: {
      CallExpression(p) {
        if (p.node.callee.name === "AddReactImport") {
          // add import if it's not there
        }
      }
    }
  };
}

如果文件/树的顶部没有import React from 'react';,那么如何添加min-width: 100% max-width: 100%

我认为比答案更重要的是你如何找到它。请告诉我,因为我很难找到有关如何开发Babel插件的信息来源。我现在的来源是:Plugin HandbookBabel TypesAST Specthis blog postAST explorer。感觉就像用英语 - 德语词典试着说德语一样。

2 个答案:

答案 0 :(得分:2)

export default function ({types: t }) {
  return {
    visitor: {
      Program(path) {
        const identifier = t.identifier('React');
        const importDefaultSpecifier = t.importDefaultSpecifier(identifier);
        const importDeclaration = t.importDeclaration([importDefaultSpecifier], t.stringLiteral('react'));
        path.unshiftContainer('body', importDeclaration);
      }
    }
  };
}

答案 1 :(得分:0)

我通常为此目的有帮手。如果要注入代码,只需使用@babel/parser为其生成AST。然后根据需要注入它。

我也同意,即使在2019年,信息仍然很少。我实际上是通过研究babel源代码,查看所有工具({{1},typestraversepath等来获取大部分信息的...),他们使用的助手,现有插件(例如code-frame,以了解JS中的基本工具),webpack istanbul等...

例如:babel-loader并未在任何地方进行详细说明,但是您可以找到它的源代码here(非常有趣,它接受单个节点或节点数组!)

策略

在这种情况下,我会:

  1. 使用实用程序功能从源(unshiftContainer)生成AST
  2. 在我的插件开始时一次准备一次AST
  3. 仅在找到特定的函数调用后,才将其注入到parseSource(即根路径)中

代码

Program

陷阱

由于您要添加导入语句,因此babel在不启用正确的插件且没有将程序类型设置为/** * Helper: Generate AST from source through `@babel/parser`. * Copied from somewhere... I think it was `@babel/traverse` * @param {*} source */ export function parseSource(source) { let ast; try { source = `${source}`; ast = parse(source); } catch (err) { const loc = err.loc; if (loc) { err.message += "\n" + codeFrameColumns(source, { start: { line: loc.line, column: loc.column + 1, }, }); } throw err; } const nodes = ast.program.body; nodes.forEach(n => traverse.removeProperties(n)); return nodes; } // ... // actual plugin here const plugin = function ({ types: t }) { const importDeclaration = parseSource(`import React from 'react';`); let imported = false; let root; return { visitor: { Program(path) { root = path; }, CallExpression(path) { if (!imported && path.node.callee.name === "AddMyImport") { // add import if it's not there imported = true; root.unshiftContainer('body', importDeclaration); } } } }; }; 的情况下尝试解析它可能会很不高兴。