polyfill
babel的配置,presets是从右往左执行,plugins相反 corejs 是一个给低版本的浏览器提供接口的库,如 Promise, map, set 等 babel7的模块以@babel开始 babel7已经移除了babel-preset-stage-0这种stage的preset 一个babel的preset是一个可共享的插件包 @babel/polyfill 模块包括 core-js 和一个自定义的 regenerator runtime 模块用于模拟完整的 ES2015+ 环境 因为新的api太多了,如果引入全部的polyfill,那就太多了,所以 transform runtime 就是干这个的 Babylon 是 Babel 的解析器。最初是 从Acorn项目fork出来
babel-polyfill
通过修改全局方法和原型 如果直接用 @babel/polyfill 3种方式(入口,文件入口,和env的useBuildin), 缺点 会引入多余的代码,但是不用手动配置太多东西,但是会污染全局变量,如果不希望这样
transform-runtime
npm install --save-dev @babel/plugin-transform-runtime
npm install --save @babel/runtime
babel在polyfill一些方法时,默认就加到每个需要这个方法的文件头部,造成大量的代码重复,runtime插件还可以创建一个沙箱环境,避免代码污染,所以在写一些库或者插件应该使用这个
{
"plugins": [
[
"@babel/plugin-transform-runtime",
{
"absoluteRuntime": false,
"corejs": false,
"helpers": true,
"regenerator": true,
"useESModules": false,
"version": "7.0.0-beta.0"
}
]
]
}
// 定义corejs版本重写helper来源库,corejs:2只支持全局变量(例如Promise)和静态属性(例如Array.from),而corejs:3还支持实例属性(例如[].Includes)。
// 默认不支持提案,如要支持 ['@babel/plugin-transform-runtime', { corejs: 3, proposals: true }]
//corejs Install command
//false npm install --save @babel/runtime
//2 npm install --save @babel/runtime-corejs2
//3 npm install --save @babel/runtime-corejs3
core-js
// polyfill all `core-js` features:
import "core-js";
// polyfill only stable `core-js` features - ES and web standards:
import "core-js/stable";
// polyfill only stable ES features:
import "core-js/es";
babel
const presets = [
[
"@babel/env",
{
targets: {
edge: "17",
firefox: "60",
chrome: "67",
safari: "11.1",
},
useBuiltIns: "usage",
// 这个配置表示 @babel/preset-env 怎么处理 polyfills
// 在使用"@babel/env"这个preset时,有这个配置,就会只加载需要的新语法,就和用了 transform runtime 一样
// 当这个值是 usage时, 就不要在webpack入口和文件入口引入有两种下边配置
1. corejs: { version: 3,proposals: true},
// 这样会开启core-js支持的所有提案 ,默认是2
// 3 要手动安装 npm install --save core-js@^3
2. shippedProposals: true
// 如果是true就会开启已经发布的提案
// 如果配置是 entry 就在源代码的第一行 import("babel-polyfill")
},
],
];
module.exports = { presets };
同样移除了@babel/polyfill的 proposal语法,现在@babel/polyfill只是 code-js v2.0的别名而已 ,如果需要再使用,要使用引入
// core-js v2
// Stage 3
import "core-js/fn/string/trim-left";
import "core-js/fn/string/trim-right";
import "core-js/fn/string/match-all";
import "core-js/fn/array/flat-map";
import "core-js/fn/array/flatten"; // RENAMED
import "core-js/fn/global";
// Stage 1
import "core-js/fn/symbol/observable";
import "core-js/fn/promise/try";
import "core-js/fn/observable";
// Stage 1 Math Extensions
import "core-js/fn/math/clamp";
import "core-js/fn/math/deg-per-rad";
import "core-js/fn/math/degrees";
import "core-js/fn/math/fscale";
import "core-js/fn/math/iaddh";
import "core-js/fn/math/isubh";
import "core-js/fn/math/imulh";
import "core-js/fn/math/rad-per-deg";
import "core-js/fn/math/radians";
import "core-js/fn/math/scale";
import "core-js/fn/math/umulh";
import "core-js/fn/math/signbit";
// Stage 1 "of and from on collection constructors"
import "core-js/fn/map/of";
import "core-js/fn/set/of";
import "core-js/fn/weak-map/of";
import "core-js/fn/weak-set/of";
import "core-js/fn/map/from";
import "core-js/fn/set/from";
import "core-js/fn/weak-map/from";
import "core-js/fn/weak-set/from";
// Stage 0
import "core-js/fn/string/at";
// Nonstandard
import "core-js/fn/object/define-getter";
import "core-js/fn/object/define-setter";
import "core-js/fn/object/lookup-getter";
import "core-js/fn/object/lookup-setter";
// import "core-js/fn/map/to-json"; // Not available standalone
// import "core-js/fn/set/to-json"; // Not available standalone
import "core-js/fn/system/global";
import "core-js/fn/error/is-error";
import "core-js/fn/asap";
// Decorator metadata? Not sure of stage/proposal
import "core-js/fn/reflect/define-metadata";
import "core-js/fn/reflect/delete-metadata";
import "core-js/fn/reflect/get-metadata";
import "core-js/fn/reflect/get-metadata-keys";
import "core-js/fn/reflect/get-own-metadata";
import "core-js/fn/reflect/get-own-metadata-keys";
import "core-js/fn/reflect/has-metadata";
import "core-js/fn/reflect/has-own-metadata";
import "core-js/fn/reflect/metadata";
peerDependencies are dependencies expected to be used by your code, as opposed to dependencies only used as an implementation detail. babel插件的名字可以简写
- "presets": ["@babel/preset-react"],
+ "presets": ["@babel/react"], // this is equivalent
- "plugins": ["@babel/transform-runtime"],
+ "plugins": ["@babel/plugin-transform-runtime"], // same
@babel/plugin-transform-function-bind is now @babel/plugin-proposal-function-bind (Stage 0)
@babel/plugin-transform-class-properties is now @babel/plugin-proposal-class-properties (Stage 3)
// @name @babel/plugin-transform-runtime
A plugin that enables the re-use of Babel's injected helper code to save on codesize
// dev
npm install --save-dev @babel/plugin-transform-runtime
// prod
npm install --save @babel/runtime
// 解析export default babel6之后,对export default支持不好
// yarn add -D babel-plugin-add-module-exports
{
"presets": [["@babel/env", { "modules": "commonjs" }]],
"plugins": ["add-module-exports"]
}
// @name @babel/plugin-proposal-object-rest-spread
// 对象展开符 {...a}
// @name @babel/plugin-proposal-class-properties
// @eg 类的用法
class Bork {
static a = "foo";
}
// @name ["@babel/plugin-proposal-decorators", { "legacy": true }]
// 装饰器
demo config
{
"presets": [
[
"@babel/env",
{
"targets": {
"chrome": "66"
},
"corejs": {
"version": 2
},
"useBuiltIns": "usage",
"modules": "commonjs"
}
],
"@babel/react"
],
"plugins": [
[
"@babel/plugin-proposal-decorators",
{
"legacy": true
}
],
[
"@babel/plugin-proposal-class-properties",
{
"loose": true
}
],
"add-module-exports",
[
"import",
{
"libraryName": "antd",
"libraryDirectory": "es",
"style": true
}
]
]
}
自定义插件
1. 配置插件
{
"presets": [
"@babel/env"
],
"plugins": [
[
"@babel/huahua", {"libs" : ["lodash"]}
]
]
}
2. 写好插件,放到 @babel 目录下
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _helperPluginUtils = require("@babel/helper-plugin-utils");
var _core = require("@babel/core");
var types = require("@babel/types");
var _default = (0, _helperPluginUtils.declare)(api => {
api.assertVersion(7);
return {
name: "huahua",
visitor: {
ImportDeclaration(path, ref){
// 当前节点
const node = path.node;
// 配置支持的库
const libs = ref.opts.libs;
// 当前的库
const lib = node.source.value;
if(libs.indexOf(lib) > -1){
let vars = node.specifiers;
if(vars[0].type !== 'ImportDefaultSpecifier'){
let imports = vars.map(item => {
return types.ImportDeclaration(
[types.ImportDefaultSpecifier(item.local)],
types.StringLiteral( `${node.source.value}/${item.local.name}`)
)
})
path.replaceWithMultiple(imports)
}
}
}
}
};
});
exports.default = _default;
babel处理过程
parse :词法分析 , 词法分析阶段把字符串形式的代码转换为 令牌(tokens) 流 和 语法分析 语法分析阶段会把一个令牌流转换成 AST 的形式 transform 转换步骤接收 AST 并对其进行遍历,在此过程中对节点进行添加、更新及移除等操作 @babel/traverse
// 访问器模式遍历树,入和出两个方法,默认就是入
// 有两个参数 一个是 Path 一个是State
const MyVisitor = {
Identifier: {
enter() {
console.log("Entered!");
},
exit() {
console.log("Exited!");
}
}
};
const MyVisitor = {
Identifier(path ,state){
// state.opts 就是babelrc配置的选项
}
};
generate 把最终的 AST 转换成字符串形式的代码