npm(babel-loader之babel/core)

428 阅读2分钟

babel/core

babel-loader的transform是通过引入babel/core的transform进行代码转换的,然而babel/core的transform里又进行了一次封装通过trasnformamation进行转换,babel/core实际上的作用就是调用babel的插件转换代码后将代码返回

"use strict";
//babel/transform.js
Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.transformSync = exports.transformAsync = exports.transform = void 0;

function _gensync() {
  const data = require("gensync");
  // gensync库封装generator函数,返回一个新的函数,其有不同的使用方式:
  // 同步使用(sync)
  // 异步调用,封装成promise,在then方法中获取结果(async)
  // 传入回调使用errback
  console.log(data, 'data')
  _gensync = function () {

    return data;
  };

  return data;
}

var _config = require("./config");

var _transformation = require("./transformation");

const transformRunner = _gensync()(function* transform(code, opts) {
  //gensync会将结果传递到yield* 然后执行yield*
  const config = yield* (0, _config.default)(opts);
  //执行完之后再去执行下一步代码
  if (config === null) return null;
  //将全局信息和需要转换的代码,传递给transformation去进行转换
  const res = yield* (0, _transformation.run)(config, code);
  //得到结果返回结果
  return res
});

const transform = function transform(code, opts, callback) {
  //code'接收到要转换的代码
  //opts 要转换代码的信息
  //callback 是回调函数,
  if (typeof opts === "function") {
    callback = opts;
    opts = undefined;
  }
    //函数的调用顺序
    //因为提前声明了transromRunner
  if (callback === undefined) return transformRunner.sync(code, opts);
  //因为有回调所以传入了回调
  transformRunner.errback(code, opts, callback);
};

exports.transform = transform;
const transformSync = transformRunner.sync;
exports.transformSync = transformSync;
const transformAsync = transformRunner.async;
exports.transformAsync = transformAsync;

transfroamation

transfromation是babel/core的核心,transfromation返回.run方法,在transfrom.js里也是通过transfromation的.run方法进行转换代码

  //transfromation.run代码片段
  const file = yield* (0, _normalizeFile.default)(config.passes, (0, _normalizeOpts.default)(config), code, ast);
  //通过_normalizefile.default将代码转为ASt树,normalize是babel封装的方法,其内部调用的是babel/parser方法
  const opts = file.opts;
  try {
    yield* transformFile(file, config.passes);
    //transformfile方法利用babel/traverse,将代码转换为目标代码
  } catch (e) {
    var _opts$filename;

    e.message = `${(_opts$filename = opts.filename) != null ? _opts$filename : "unknown"}: ${e.message}`;

    if (!e.code) {
      e.code = "BABEL_TRANSFORM_ERROR";
    }

    throw e;
  }
  let outputCode, outputMap;

  try {
    if (opts.code !== false) {
      ({
        outputCode,
        outputMap
        //调用generates 遍历ast并且输出代码
        //generate方法实际上调用的是babel/generator
      } = (0, _generate.default)(config.passes, file));
      

      function* transformFile(file, pluginPasses) {
  for (const pluginPairs of pluginPasses) {
    const passPairs = [];
    const passes = [];
    const visitors = [];

    for (const plugin of pluginPairs.concat([(0, _blockHoistPlugin.default)()])) {
      const pass = new _pluginPass.default(file, plugin.key, plugin.options);
      passPairs.push([plugin, pass]);
      passes.push(pass);
      visitors.push(plugin.visitor);
    }

    for (const [plugin, pass] of passPairs) {
      const fn = plugin.pre;

      if (fn) {
        const result = fn.call(pass, file);
        yield* [];

        if (isThenable(result)) {
          throw new Error(`You appear to be using an plugin with an async .pre, ` + `which your current version of Babel does not support. ` + `If you're using a published plugin, you may need to upgrade ` + `your @babel/core version.`);
        }
      }
    }

    const visitor = _traverse().default.visitors.merge(visitors, passes, file.opts.wrapPluginVisitorMethod);
   //_traverse实际上调用的是引入的babel/parser
    (0, _traverse().default)(file.ast, visitor, file.scope);

    for (const [plugin, pass] of passPairs) {
      const fn = plugin.post;

      if (fn) {
        const result = fn.call(pass, file);
        yield* [];

        if (isThenable(result)) {
          throw new Error(`You appear to be using an plugin with an async .post, ` + `which your current version of Babel does not support. ` + `If you're using a published plugin, you may need to upgrade ` + `your @babel/core version.`);
        }
      }
    }
  }
}
      
      
      //normaizefile.js
      var _parser = require("../parser"); //_parser内部引入了babel/parser然后返回

var _cloneDeep = require("./util/clone-deep");

const {
  file,
  traverseFast
} = _t();

const debug = _debug()("babel:transform:file");

const LARGE_INPUT_SOURCEMAP_THRESHOLD = 1000000;

function* normalizeFile(pluginPasses, options, code, ast) {
  // console.log(pluginPasses,'pluginpass')
  code = `${code || ""}`;
  //调用parse将代码转换为Ast
  if (ast) {
    if (ast.type === "Program") {
      ast = file(ast, [], []);
    } else if (ast.type !== "File") {
      throw new Error("AST root must be a Program or File node");
    }

    if (options.cloneInputAst) {
      ast = (0, _cloneDeep.default)(ast);
    }
  } else {
    ast = yield* (0, _parser.default)(pluginPasses, options, code);
  }