babel源码解析之(@babel/plugin-transform-runtime)

本文详细解析了Babel插件@babel/plugin-transform-runtime的工作原理和配置,通过实例演示了如何使用该插件进行代码转换,减少代码体积。解释了runtime如何处理polyfill和helper函数,对比了与@babel/preset-env的区别,以及如何配置corejs、useESModules等选项。
摘要由CSDN通过智能技术生成

前言

前面我们用了一篇很长的文章介绍了@babel/preset-env,感兴趣的可以去看我之前的一篇文章babel源码解析之(@babel/preset-env),今天我们要分析的是babel的一个插件,叫@babel/plugin-transform-runtime.

简介

我们看一下官网对它的描述:

A plugin that enables the re-use of Babel’s injected helper code to save on codesize.

很简短的一个描述信息,翻译一下大概是:“抽离babel的一些公共工具类用来减少代码的大小”,虽然描述很少,但是理解起来好像比较抽象,下面我们一起结合demo一步步分析一下。

开始

我们还是继续使用我们前面的demo项目

我们先安装一下@babel/plugin-transform-runtime插件,

npm install -D @babel/plugin-transform-runtime

然后我们在src目录底下创建一个demo.runtime.js用来测试,

src/demo.runtime.js:

const fn = () => {
   };

new Promise(() => {
   });

class Test {
   
    say(){
   }
}

const c = [1, 2, 3].includes(1);
var a = 10;

function* helloWorldGenerator() {
   
    yield 'hello';
    yield 'world';
    return 'ending';
}

可以看到,除了之前的一些代码外,我们还加入了一个es6的generator函数,我们直接用一下@babel/plugin-transform-runtime插件,然后用它的默认设置,

babel.config.js:

module.exports = {
   
    plugins: [
        [
            "@babel/plugin-transform-runtime",
            {
   
                "absoluteRuntime": false,
                "corejs": 2,
                "helpers": true,
                "regenerator": true,
                "useESModules": false,
                "version": "7.0.0-beta.0"
            }
        ]
    ]
};

我们运行babel编译看结果:

➜  babel-demo git:(v0.0.1) ✗ npx babel ./src/demo.runtime.js -o ./lib/demo.runtime.js

lib/demo.runtime.js:

const fn = () => {
   };

new Promise(() => {
   });

class Test {
   
  say() {
   }

}

const c = [1, 2, 3].includes(1);
var a = 10;

function* helloWorldGenerator() {
   
  yield 'hello';
  yield 'world';
  return 'ending';
}

可以看到,经过runtime插件处理后代码并没有改变,这是为什么呢?因为在我们runtime插件的配置中我们默认是关闭掉一些功能的,比如我们把runtime的corejs打开,

babel.config.js:

module.exports = {
   
    plugins: [
        [
            "@babel/plugin-transform-runtime",
            {
   
                "absoluteRuntime": false,
                "corejs": 2,
                "helpers": true,
                "regenerator": true,
                "useESModules": false,
                "version": "7.0.0-beta.0"
            }
        ]
    ]
};

再次运行看结果:

➜  babel-demo git:(v0.0.1) ✗ npx babel ./src/demo.runtime.js                         
import _Promise from "@babel/runtime-corejs2/core-js/promise";

const fn = () => {
   };

new _Promise(() => {
   });

class Test {
   
  say() {
   }

}

const c = [1, 2, 3].includes(1);
var a = 10;

function* helloWorldGenerator() {
   
  yield 'hello';
  yield 'world';
  return 'ending';
}

➜  babel-demo git:(v0.0.1)

可以看到,自动帮我们引入了一个polyfill(_Promise),那小伙伴要疑问了,es6的语法没转换?是的! 因为runtime不做这些语法的转换,它只能算是一个转换帮助类、一个自动添加polyfill的工具,es6语法转换我们上一节用了preset-env,所以我们把preset-env加上,然后把polyfill去掉,最后runtime配置还原到默认配置,

babel.config.js:

module.exports = {
   
    presets:[
        [
            "@babel/preset-env"
        ]
    ],
    plugins: [
        [
            "@babel/plugin-transform-runtime",
            {
   
                "absoluteRuntime": false,
                "corejs": false,
                "helpers": true,
                "regenerator": true,
                "useESModules": false,
                "version": "7.0.0-beta.0"
            }
        ]
    ]
};

再次运行babel看效果:

➜  babel-demo git:(v0.0.1) ✗ npx babel ./src/demo.runtime.js -o ./lib/demo.runtime.js

lib/demo.runtime.js:

"use strict";

var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");

var _regeneratorRuntime2 = require("@babel/runtime/regenerator");

var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));

var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));

var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));

var _marked = /*#__PURE__*/_regeneratorRuntime2.mark(helloWorldGenerator);

var fn = function fn() {
   };

new Promise(function () {
   });

var Test = /*#__PURE__*/function () {
   
  function Test() {
   
    (0, _classCallCheck2.default)(this, Test);
  }

  (0, _createClass2.default)(Test, [{
   
    key: "say",
    value: function say() {
   }
  }]);
  return Test;
}();

var c = [1, 2, 3].includes(1);
var a = 10;

function helloWorldGenerator() {
   
  return _regenerator.default.wrap(function helloWorldGenerator$(_context) {
   
    while (1) {
   
      switch (_context.prev = _context.next) {
   
        case 0:
          _context.next = 2;
          return 'hello';

        case 2:
          _context.next = 4;
          return 'world';

        case 4:
          return _context.abrupt("return", 'ending');

        case 5:
        case "end":
          return _context.stop();
      }
    }
  }, _marked);
}

看结果也看不出什么,那runtime到底为我们做了什么呢?我们试一下如果我们不使用runtime插件,直接使用preset-env看结果:

babel.config.js

module.exports = {
   
    presets:[
        [
            "@babel/preset-env"
        ]
    ],
    plugins: [
        // [
        //     "@babel/plugin-transform-runtime",
        //     {
   
        //         "absoluteRuntime": false,
        //         "corejs": false,
        //         "helpers": true,
        //         "regenerator": true,
        //         "useESModules": false,
        //         "version": "7.0.0-beta.0"
        //     }
        // ]
    ]
};

运行babel看结果:

"use strict";

var _marked = /*#__PURE__*/regeneratorRuntime.mark(helloWorldGenerator);

function _classCallCheck(instance, Constructor) {
    if (!(instance instanceof Constructor)) {
    throw new TypeError("Cannot call a class as a function"); } }

function _defineProperties(target, props) {
    for (var i = 0; i < props.length; i++) {
    var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }

function _createClass(Constructor, protoProps, staticProps) {
    if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }

var fn = function fn() {
   };

new Promise(function () {
   });

var Test = /*#__PURE__*/function () {
   
  function Test() {
   
    _classCallCheck(this, Test);
  }

  _createClass(Test, [{
   
    key: "say",
    value: function say() {
   }
  }]);

  return Test;
}();

var c = [1, 2, 3].includes(1);
var a = 10;

function helloWorldGenerator() {
   
  return regeneratorRuntime.wrap(function helloWorldGenerator$(_context) {
   
    while (1) {
   
      switch (_context.prev = _context.next) {
   
        case 0:
          _context.next = 2;
          return 'hello';

        case 2:
          _context.next = 4;
          return 
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值