Babel

yuhuo2022-10-28开发库工具库
参考链接

整体架构

  • 编译
    • @babel/core:集成下列多个包的功能(所以下列包可以不用学)
    • @babel/parser:代码转AST
    • @babel/traverse:修改AST
    • @babel/generator:AST转代码
    • ...
  • 工具
    • @babel/cli:通过命令行和配置参数(或配置文件)直接编译生成目标代码
    • @babel/register:nodejs 中自动通过 babel 转换 require 进来的代码
    • babel-loader:webpack装载器,将源码和配置对象(或配置文件)传入方法执行返回目标代码
  • 预设
    • @babel/preset-env:es6+ 转 es5,并可以通过 corejs 添加全局补丁(完整引入和按需引入)
    • @babel/preset-react:jsx 转 React.createElement()
    • @babel/preset-typescript:ts 转 js
    • @babel/preset-flow:使用了 flow 的 js 转 js
  • 插件
    • @babel/plugin-transform-runtime:局域补丁-按需引入,不会污染全局变量
    • @babel/plugin-transform-arrow-functions:箭头函数转普通函数
    • ...
  • 补丁
    • @babel/polyfill:补丁库,全局补丁-完整引入不推荐
    • core-js:补丁库,在 @babel/preset-env 生成的代码中使用
    • @babel/runtime-corejs3:补丁辅助,在 @babel/plugin-transform-runtime 生成的代码中使用
    • @babel/runtime:补丁辅助,在 @babel/plugin-transform-runtime 生成的代码中使用(未配置 corejs 参数时)

@babel/cli

1. 安装

# 安装核心包和命令行工具
npm install --save-dev @babel/core @babel/cli

# 安装预设和插件
npm install --save-dev @babel/preset-env @babel/plugin-transform-arrow-functions @babel/plugin-transform-runtime

# 安装补丁
npm install --save core-js

2. 配置文件

必须在项目根目录下,包含以下多种方式

  • babel.config.json推荐
  • babel.config.js:动态配置
  • .babelrc.json
  • .babelrc.js
  • .babelrc:同 json
  • package.json:增加 babel 字段
{
    // 插件(先插件,从前到后)
    "plugins": [
        "@babel/plugin-transform-arrow-functions",
    ],
    // 预设(后预设,从后到前)
    "presets": [
        [
            "@babel/preset-env",
            {
                // 需要支持的目标浏览器版本,无此字段则默认需要全部支持
                "targets": {
                    "edge": "17",
                    "firefox": "60",
                    "chrome": "67",
                    "safari": "11.1"
                },
                // 全局补丁
                // false:无(默认)
                // "entry":完整引入(需要在入口文件手动引入 core-js/stable 和 regenerator-runtime/runtime)
                // "usage":自动按需引入
                "useBuiltIns": "usage",
                // 补丁版本(当 useBuiltIns 为非 false 时需要指定)
                "corejs": 3
            }
        ]
    ],
}

3. 执行编译

# 把src目录的JavaScript文件编译到lib目录
npx babel src --out-dir lib

# 在命令行指定预设
npx babel src --out-dir lib --presets=@babel/env

# 在命令行指定插件
npx babel src --out-dir lib --plugins=@babel/plugin-transform-arrow-functions

源文件

let a = 1;
let b = () => {};
[].includes(1);

生成文件

"use strict";

require("core-js/modules/es7.array.includes.js");
var a = 1;
var b = function b() {};
[].includes(1);

4. 命令参数

命令参数缩写作用示例
--out-file-o输出文件名称babel a.js -o b.js
--watch-w实时监控输出babel a.js -o b.js -w
--source-maps-s输出map文件babel a.js -o b.js -s
--source-maps inline-s inline行内source mapbabel a.js -o b.js -s inline
--out-dir-d编译文件夹babel src -d dist
--ignore忽略某些文件babel src -d dist --ignore src/**/*.spec.js
--copy-files复制不需要编译的文件babel src -d dist --copy-files
--plugins指明使用插件babel a.js -o b.js --plugins @babel/plugin-transform-arrow-functions
--presets指明使用预设babel src -d dist --presets @babel/preset-env

@babel/core

1. 安装

# 安装核心包
npm install --save-dev @babel/core

# 安装预设和插件
npm install --save-dev @babel/preset-env @babel/plugin-transform-arrow-functions

2. 编译

const babel = require("@babel/core");
const sourceCode = `
    import abc from "abc";
    const arrowFunc = () => {
    let a = 1;
	console.log(this);
    [].includes(1);
}`;
// 源码转目标AST和目标代码
var target1 = babel.transformSync(sourceCode, {
    // 是否生成目标代码,默认true
    code: true,
    // 是否生成抽象语法树,默认false
    ast: true,
    // 预设(同时配置文件中的预设和插件配置也生效)
    presets: ["@babel/preset-env"],
    // 插件
    plugins: [
        [
            "@babel/plugin-transform-runtime",
            {
                corejs: 3,
            },
        ],
    ],
});
console.log(target1.code);
console.log(target1.ast);

// 源码转AST
const AST = babel.parseSync(sourceCode);

// 遍历修改AST
babel.traverse(AST, {
    CallExpression(p) {
        // console.log(p.node)
    },
});

// AST转目标AST和目标代码
var target2 = babel.transformFromAstSync(AST, null, {
    ast: true,
    presets: ["@babel/preset-env"],
});
console.log(target2.code);
console.log(target2.ast);

@babel/polyfill

1. 安装

npm install --save @babel/polyfill

2. 引入

需要转换的文件入口加入引用代码

require("@babel/polyfill");

Webpack入口处进行引入

module.exports = {
  entry: ["@babel/polyfill", "./src/index.js"],
};

@babel/plugin-transform-runtime

1. 安装

# 安装核心包和命令行工具
npm install --save-dev @babel/core @babel/cli

# 安装转换插件
npm install --save-dev @babel/plugin-transform-runtime

# 安装补丁辅助包
npm install --save @babel/runtime-corejs3

2. 配置文件

{
    "plugins": [
        // 局域补丁-按需引入(目前不能指定 targets,当前配置使 presets 中的全局补丁失效)
        ["@babel/plugin-transform-runtime",{
            "corejs": 3
        }]
    ]
}

3. 执行编译

源文件

const promsies = new Promise();
var a = [1,2,3].includes(8);

生成文件

var _context;
import _Promise from "@babel/runtime-corejs3/core-js-stable/promise";
import _includesInstanceProperty from "@babel/runtime-corejs3/core-js-stable/instance/includes";
const promsies = new _Promise();
var a = _includesInstanceProperty(_context = [1, 2, 3]).call(_context, 8);

4. @babel/preset-env + @babel/plugin-transform-runtime

源文件

class People {}
[].includes(1);

示例A

仅使用 @babel/preset-env:未添加补丁,转换语法

在代码中定义了很多工具函数,造成代码冗余。

{
    "presets": [ "@babel/preset-env" ]
}
"use strict";

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); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
var People = /*#__PURE__*/_createClass(function People() {
  _classCallCheck(this, People);
});
[].includes(1);

示例B

仅使用 @babel/plugin-transform-runtime:添加补丁,未转换语法

{
    "plugins": [
        ["@babel/plugin-transform-runtime",{
            "corejs": 3
        }]
    ]
}
var _context;
import _includesInstanceProperty from "@babel/runtime-corejs3/core-js-stable/instance/includes";
class People {}
_includesInstanceProperty(_context = []).call(_context, 1);

示例C

仅使用 @babel/plugin-transform-runtime,未指定 corejs 字段:未添加补丁,未转换语法

{
    "plugins": [
        ["@babel/plugin-transform-runtime"]
    ]
}
class People {}
[].includes(1);

示例D

使用 @babel/preset-env + @babel/plugin-transform-runtime,未指定 corejs 字段:未添加补丁,转换语法

将代码中冗余的工具函数从 @babel/runtime 辅助包中引入。

{
    "plugins": [
        ["@babel/plugin-transform-runtime"]
    ],
    "presets": [ "@babel/preset-env" ]
}
"use strict";

var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
var People = /*#__PURE__*/(0, _createClass2["default"])(function People() {
  (0, _classCallCheck2["default"])(this, People);
});
[].includes(1);

示例E

使用 @babel/preset-env + @babel/plugin-transform-runtime:添加补丁,转换语法

将代码中冗余的工具函数和补丁都从 @babel/runtime-corejs3 辅助包中引入。

{
    "plugins": [
        ["@babel/plugin-transform-runtime",{
            "corejs": 3
        }]
    ],
    "presets": [ "@babel/preset-env" ]
}
"use strict";

var _interopRequireDefault = require("@babel/runtime-corejs3/helpers/interopRequireDefault");
var _includes = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/instance/includes"));
var _createClass2 = _interopRequireDefault(require("@babel/runtime-corejs3/helpers/createClass"));
var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime-corejs3/helpers/classCallCheck"));
var _context;
var People = /*#__PURE__*/(0, _createClass2["default"])(function People() {
  (0, _classCallCheck2["default"])(this, People);
});
(0, _includes["default"])(_context = []).call(_context, 1);

@babel/register

1. 安装

npm install --save @babel/core @babel/register @babel/preset-env

2. 配置文件

项目根目录下的 babel.config.json 文件

{
    "presets": ["@babel/preset-env"]
}

3. 运行

demo.js

const demo = () => {
    let a = 1;
  	console.log('Hello');
};
module.exports = demo;

默认情况

const demo = require('./demo');

console.log(`${demo}`);
// 打印结果
// () => {
//     let a = 1;
//     console.log('Hello');
// }

使用 @babel/register

require('@babel/register')
const demo = require('./demo');

console.log(`${demo}`);
// 打印结果
// function demo() {
//   var a = 1;
//   console.log('Hello');
// }
Last Updated 2024/3/14 09:51:53