hn-failte's blog hn-failte's blog
首页
  • 前端文章

    • JavaScript
    • Vue
    • React
    • Webpack
    • 混合开发
    • 小程序
  • 学习笔记

    • 《JavaScript教程》笔记
    • 《JavaScript高级程序设计》笔记
    • 《ES6 教程》笔记
    • 《Vue》笔记
    • 《React》笔记
    • 《TypeScript 从零实现 axios》
    • 《Git》学习笔记
    • TypeScript笔记
    • JS设计模式总结笔记
    • 圆角边框锯齿问题
    • 各国语言正则
  • HTML&CSS
  • HTML
  • CSS
  • CSS预处理
  • 技术文档
  • GitHub技巧
  • Nodejs
  • 博客搭建
  • 算法
  • 数据库
  • 操作系统
  • 工具
  • 学习
  • 面试
  • 心情杂货
  • 前端相关
  • 实用技巧
  • 友情链接
关于
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

hn-failte

前端cv仔
首页
  • 前端文章

    • JavaScript
    • Vue
    • React
    • Webpack
    • 混合开发
    • 小程序
  • 学习笔记

    • 《JavaScript教程》笔记
    • 《JavaScript高级程序设计》笔记
    • 《ES6 教程》笔记
    • 《Vue》笔记
    • 《React》笔记
    • 《TypeScript 从零实现 axios》
    • 《Git》学习笔记
    • TypeScript笔记
    • JS设计模式总结笔记
    • 圆角边框锯齿问题
    • 各国语言正则
  • HTML&CSS
  • HTML
  • CSS
  • CSS预处理
  • 技术文档
  • GitHub技巧
  • Nodejs
  • 博客搭建
  • 算法
  • 数据库
  • 操作系统
  • 工具
  • 学习
  • 面试
  • 心情杂货
  • 前端相关
  • 实用技巧
  • 友情链接
关于
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • Webpack

    • webpack 之 tapable 的讲解与使用
    • 使用Gulp4.0搭建ts学习环境
    • eslint从愁眉苦脸到为所欲为
    • babel
      • 一、基础介绍
      • 二、基本流程
      • 三、解析器
      • 四、转换器
      • 五、生成器
      • 六、核心插件
      • 七、插件的使⽤
        • 1、安装依赖
  • React

  • JavaScript

  • Vue

  • 混合开发

  • 学习笔记

  • 小程序

  • 前端
  • Webpack
hn-failte
2022-01-23

babel

# babel

# 一、基础介绍

Babel 是⼀个 JavaScript 编译器。

Babel 是⼀个⼯具链(依赖于生态,如:插件),主要⽤于将采⽤ ECMAScript 2015+ 语法编写的代码转换为向后兼容的 JavaScript 语法,以便能够运⾏在当前和旧版本的浏览器或其他环境中。

  • 语法转换
  • Polyfill
  • 源码转换

# 二、基本流程

Babel⼯作原理本质上就是三个步骤:parse、transform 和 generator。

const { parse } = require('@babel/parser');
const { default: generate } = require('@babel/generator');

const source = `const name = 'babel'`;

const ast = parse(source);
console.log(ast.program.body[0], ast.program.body[0].declarations);

/**
 * 在这里做代码转换
 */

const code = generate(ast);
console.log(code);
1
2
3
4
5
6
7
8
9
10
11
12
13
14

# 三、解析器

在babel中编译器插件是 @babel/parser,其作⽤就是将源码转换为 AST

# 四、转换器

插件发挥作⽤的地⽅基本就是在 tranfrom 这个流程了,当源码通过 parse ⽣成了 ast 后,即可通过转换插件,操作 ast。

@babel/types

用于创建、修改、删除、查找ast节点。

@babel/traverse

⽤于对 ast 进⾏遍历,在遍历的过程中可以定义回调函数,回调函数的参数提供了丰富的增、删、改、查以及类型断⾔的⽅法,⽐如 replaceWith / remove / find / isMemberExpression。

# 五、生成器

使⽤的插件是 @babel/generator,其作⽤就是将 ast 重新⽣成指定类型的代码。

const { parse } = require('@babel/parser');
const { default: traverse } = require('@babel/traverse');
const { default: generate } = require('@babel/generator');

const source = `const name = 'babel'`; // 原始代码
const ast = parse(source);

traverse(ast, {
	VariableDeclaration(path) {
		const { node } = path;
		if (node.kind === 'const') {
			path.node.kind = "var";
		}
	}
});

const code = generate(ast, {}, source);
console.log(code);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

# 六、核心插件

babel-core

包含 babel 的核心功能的封装,如 @babel/parse、@babel/generator、@babel/types、@babel/traverser 等等。

const babel = require("@babel/core");

const constPlugin = ({ types: t }) => ({
	visitor: {
 		VariableDeclaration(path) {
			const { node } = path;
			if (node && node.kind === 'const') node.kind = "var";
		}
	}
})

const code = `const name = babel;`;

babel.transform(code, {
	plugins: [constPlugin],
	babelrc: false
}, (err, result) => {
	if (!err) console.log(result.code)
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

# 七、插件的使⽤

执行时序

插件在 Presets 前运⾏

执行顺序

插件从前往后执行

插件的短名称

如果插件名称为 @babel/plugin-XXX,可以使⽤短名称@babel/XXX

如果插件名称为 babel-plugin-XXX,可以使⽤短名称 XXX

Babel 的插件分为两种: 语法插件和转换插件。

语法插件

作⽤于 @babel/parser,在将代码解析为 AST 时解析语法

转换插件

作⽤于 @babel/core,在对 AST 进行遍历时进行转换。

# 1、安装依赖

@babel/core: 核⼼库 @babel/cli: CLI命令⾏⼯具

npm install -D @babel/core @babel/cli

# 2、配置

项⽬维度的配置⽂件,也叫全局配置文件,一般文件名为 babel.config.js 或 .babelrc。

相对路径的配置⽂件,一般文件名为 .babelrc,babel 在决定⼀个⽂件应⽤什么配置时,会执⾏如下策略(文件必须在当前项目): 1、从当前路径递归往上查找 .babelrc ⽂件 2、查找全局配置合并。

# presets

执行顺序

Preset 从后往前执行

插件的集合

@babel/preset-env 用于对所使⽤的⽬标浏览器中缺失的功能进⾏代码转换和 polyfill。

@babel/preset-env 默认包含的插件将⽀持所有最新的 JS 特性,如 ES2015、ES2016等(不包含 stage 阶段),将其转换成ES5代码。

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

@babel/preset-env 会根据⽬标环境,⽣成插件列表来编译。对基于浏览器或 webview 的项⽬,官⽅推荐使⽤ .browserslistrc ⽂件来指定⽬标环境。

默认情况下,若没有在 Babel 配置⽂件中设置 targets 或 ignoreBrowserslistConfig,@babel/preset-env 会使⽤ browserslist 配置源。

# Polyfill

@babel/polyfill 模块包括 core-js 和⼀个⾃定义的 regenerator runtime 模块,可以模拟完整的 ES2015+ 环境(不包含第4阶段前的提议)。

从 V7.4.0 版本开始,官⽅不再推荐使⽤此模块

# preset 与 polyfill

@babel/preset-env 与 @babel/polyfill 的相关参数如下:

  • targets: ⽀持的⽬标浏览器的列表

  • useBuiltIns: 参数有 "entry"、"usage"、false 三个值。默认值是 false,此参数决定了 babel 打包时 如何处理 @babel/polyfilll 语句

  • corejs: useBuiltIns 设置值为 usage 时有效 (若不设置,会给出警告,默认使⽤的是"corejs": 2)

core-js@2 分⽀中已经不会再添加新特性,新特性都会添加到 core-js@3。

useBuiltIns的不同配置如下:

  • entry: 去掉⽬标浏览器已⽀持的 polyfilll 模块,将浏览器不⽀持的都引⼊对应的 polyfill 模块
  • usage: 打包时会⾃动根据实际代码的使⽤情况,结合 targets 引⼊代码⾥实际⽤到部分 polyfill 模块
  • false: 不会⾃动引⼊ polyfilll 模块,对polyfilll模块屏蔽
{
	"presets": [
		["@babel/preset-env", {
			"useBuiltIns": "usage",
			"corejs": 3
 		}]
	]
}
1
2
3
4
5
6
7
8

# @babel/runtime

base.js

export class Base {
	console(message) {
		console.log(message)
	}
}
1
2
3
4
5

index.js

import { Base } from './base'

class A extends Base {
	console(message) {
		super.console('a:', message)
	}
}

let a = new A()
a.console('done')
1
2
3
4
5
6
7
8
9
10

两个⽂件在编译 class 语法时,都用到了辅助⽅法:_createClass、 _classCallCheck。

有相同代码的地方就有优化,因此这里引用了 @babel/plugin-transform-runtime。

@babel/plugin-transform-runtime 就是⼀个可用于解决重复进行 Babel 注⼊以缩减代码体积的插件。

{
	"presets": [
		[
			"@babel/preset-env",
			{
				"useBuiltIns": "usage",
				"corejs": 3
			}
		]
	],
	"plugins": [
		["@babel/plugin-transform-runtime"]
	]
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14

引入后,相同的辅助⽅法不会在每个⽂件中单独定义,⽽是从 @babel/runtime/helpers 中统⼀引⼊。

@babel/plugin-transform-runtime 还能为代码创建⼀个沙盒环境。

在使⽤ @babel/polyfill 及其提供的内置程序(如:ES6 的特性 ),会在全局作用域中进行挟持,虽然解决了兼容问题,但是若代码是要发布到社区的库,又或⽆法决定代码运⾏的环境,则劫持就会成为污染。

@babel/plugin-transform-runtime 的另一个作用则是将这些内置别名作为 core-js 的别名,可以进行使⽤,但并不会污染全局作用域。

corejs选项与相关按照、说明

选项 安装命令 说明
false npm i @babel/runtime 只提供公共的帮助⽅法,⾼级语法和 API 仍需依赖 @babel/polyfill 转译
2 npm i @babel/runtime-corejs2 ⽀持全局变量(例如Promise)和静态属性(例如Array.from)
3 npm i @babel/runtime-corejs3 还⽀持实例属性(例如[].includes)
{
	"presets": [
		["@babel/preset-env"]
	],
	"plugins": [
		["@babel/plugin-transform-runtime", {
			"corejs": 3
		}]
	]
}
1
2
3
4
5
6
7
8
9
10
编辑 (opens new window)
#babel
上次更新: 2024/01/26, 18:22:27
eslint从愁眉苦脸到为所欲为
React中context的用法

← eslint从愁眉苦脸到为所欲为 React中context的用法→

最近更新
01
safari 兼容问题笔记
01-26
02
electron 日志接入
12-26
03
vue3-template-compile
11-24
更多文章>
Theme by Vdoing | Copyright © 2017-2024 hn-failte | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式