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
:同 jsonpackage.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 map | babel 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');
// }