Babel:下一代Javascript语法编译器
定义
Babel是一个Javascript的编译器,通过它你可以将一些新版本的ECMAScript语法转换成低版本的语法。以便能够在低版本的浏览器或者其它环境平稳运行。
截至目前笔者写这篇文章的时候,babel的版本是7.10.0
实践
第一步:创建项目
mkdir babel-study && cd babel-study
第二步:初始化项目,并安装相关依赖包
npm init -y
npm i @babel/cli @babel/core @babel/preset-env --save-dev
相关依赖包说明:
@babel/cli: hello,你好,我是脚手架工具,我可以通过一些命令将源文件编译成目标代码。
@babel/core: hello,你好,我是一个代码分析选手,我负责将代码分析称ast,方便其他插件进行相关处理。
@babel/preset-env: hello,你好,我是一个语法转义器,我负责的内容是将JS的相关语法进行编译,关于转义新增的API和全局对象这个我不负责的。
第三步:配置.babelrc
楼下这几位就是常用的babel配置参数了,这里做简要介绍
presets(预设)
早期的版本其实是引入类似babel-preset-x,这种形式的包,现在官方推荐统一用@babel/preset-env,这个包来做语法转义器这部分的工作。
plugins(插件)
弥补babel本身上的功能不足,比如转义新增的API和全局对象可能就需要用到一些新的插件来做这部分工作,我们称之为补丁转义器。
ignore(忽略)
把不需要babel编译的文件写配置到这个参数里面,是一个数组的形式。
minified(压缩)
Boolean类型的,将其设置为true后,编译后的文件会被压缩。
comments(注释)
Boolean类型的,将其设置为true后,编译后的文件会有注释(你项目开发中写的注释)。
env(环境变量)
babel运行的环境变量,如果设置了BABEL_ENV则使用它,如果没有设置,它会去找有没有NODE_ENV,如果还是没有,那就是走默认development。
这里附上一份我调研后的配置文件
{
"presets": [[
"@babel/preset-env", {
// "modules": false,
"corejs": "3",
"useBuiltIns": "usage",
"targets": {
"node": "4"
// "browsers": ["last 2 versions"]
}
}
]],
"plugins": ["@babel/plugin-transform-runtime"],
"env": {
"test": {
"presets": [[
"@babel/preset-env", {
"modules": false,
"targets": {
"node": "current",
// "chrome": "83",
// "edge": "17",
// "firefox": "68",
// "ie": "11",
// "ios": "11.3",
// "safari": "5.1",
// "samsung": "9.2",
"browsers": ["last 2 versions"]
}
}
]],
"minified": true,
"comments": true,
"ignore": ["./src/test.js"]
},
"development": {
"presets": [[
"@babel/preset-env", {
"targets": {
"browsers": ["last 2 versions", "safari 7"]
}
}
]]
},
"production": {
"presets": [[
"@babel/preset-env", {
"targets": {
"browsers": ["> 1%", "last 2 versions", "not ie <= 8"]
}
}
]],
"plugins": ["@babel/runtime"],
"minified": true,
"comments": true
}
}
}
这里简要说明下,modules默认为true的,在node的环境下(支持COMMONJS),如果使用ES Module的语法(import、export),然后将其设置为false,你会发现入口文件没有被编译,所有这里把它去掉了。然后targets下面你可以单独设置相关环境的支持版本,browsers的优先级高于其他的。babel7.4.0以后,废弃了polyfill,需要单独安装core-js
第四步:编写相关测试代码
这里我们测试下ES Module写法,然后一些新的API的转义情况,比如数组的include,箭头函数、模板字符串、Promise等,这里我们不考虑相关的写法是不是冗余,单纯地就是为了测试下编译效果。
animal.js
class Animal {
constructor(name) {
this.name = name;
}
eat() {
console.log(`${this.name} is eating!`);
}
}
export default Animal;
person.js
import Animal from './animal';
class Person extends Animal {
constructor(name, sex) {
super(name);
this.name = name;
this.sex = sex;
this.sexMap = new Map([[1, '男'], [0, '女']]);
}
sing() {
console.log(`${this.name} is singing!`);
}
getSex() {
if (![0, 1].includes(this.sex)) {
return false;
} else {
return this.sexMap.get(this.sex);
}
}
testArr(arr) {
return arr.map(item => item * 2);
}
testPromise() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(2020);
}, 2000);
});
}
}
export default Person;
index.js
import Person from './person';
// 我就是试试
let ataola = new Person('ataola', 1);
ataola.eat();
ataola.sing();
const sex = ataola.getSex();
console.log(sex);
let testArr = ataola.testArr([0, 1, 2]);
console.log(testArr);
ataola.testPromise().then(res => {
console.log(res);
});
第五步:babel-cli的使用
编译项目文件
# 单纯执行, 它会在控制台打出编译后的信息
babel index.js
# 完整写法
babel index.js --out-file bundle.js
# 简写形式
babel index.js -o bundle.js
编译项目文件夹
# 完整写法
babel src -out-dir dist
# 简写形式
babel src -d dist
# 生成sourc map文件
babel src -d dist -s
babel-node
babel-cli天然自带了一个babel-node的命令,拆分一下也就是babel + node,提供了一个支持ES6的REPL环境,你可以这么玩。
# 直接进到这个环境
babel-node
# 直接执行这个文件的代码
babel-node index.js
最后附上我的测试脚本
...
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build:dir": "babel src -d dist",
"build:dir:prod": "cross-env BABEL_ENV=production babel src -d dist",
"build:dir:dev": "cross-env BABEL_ENV=development babel src -d dist",
"build:dir:test": "cross-env BABEL_ENV=test babel src -d dist",
"build:dir:s": "babel src -d dist -s",
"build:file": "babel ./test/babel_core.test.js -o bundle.js"
},
...
项目地址: https://github.com/ataola/JavaScript-Tsukuki/tree/master/code/babel-study
问题思考
在项目中使用Babel,它的作用是什么?或者这么说它的意义何在?
将高版本的JS语法转换成低版本的JS语法,可兼容不同版本的浏览器或者运行环境,划重点,解决了代码在不同版本的浏览器的兼容性问题。人的脑容量都是有限的,兼容的事情就愉快地交给它吧。
使用Babel后,把源代码编译成更复杂更难懂一坨坨的东西,我为什么要去用它?
首先,这绝对不是为了装逼,也不是为了混淆代码。我们先思考下使用高版本的语法它有什么用?有一些其实是低版本的语法糖,使用了这些我们可以减少代码量,然后减轻维护成本。但是ECMAScript它是一个语法标准,不同的JS引擎以及浏览器对它的实现和支持又不大一样,所有我们不能够保证使用高版本的语法它能够完美在各平台运行,这也就是babel的作用体现。
ES的语法有那么多版本,Babel的配置有那么多个版本,我该怎么去选择呢?
早期地预设有babel-preset-es2015、babel-preset-stage-x之类的啥的,现在官方推荐统一@babel/preset-env,脚手架统一@babel/cli,对,不成文地规定就是@babel打头基本是对的,polyfill除外。
@babel/xxx和 babel-xxx的,为什么会有两种,该用哪个?
先说结论,用前者@babel/xxx, @xxx就相当于注册了一个命名空间,特指这个是xxx下的某包,它是一个范围,是一种组织的体现形式,例如@ataola/zjt,
.babelrc文件我不写行不行,能运行吗?
如果只是创建一个.babelrc里面什么都不写,会报错,因为babel会读取里面的格式,加个{},这个是可以运行的,里面什么都不写。这里思考下babel的默认行为是什么?只是转换了Javascript的语法,而不对新的API进行转换,新的还是要用插件的。
什么是语法转义器,什么是补丁转义器?
在presets里的形如@babel/preset-env就是语法转义器,在plugins下的插件包就是补丁转义器,它们的分工不同,前者是将相关语法进行编译,后者弥补了前者的一些不足,故称之为补丁。
targets里设置browsers的优先级高,还是直接设置浏览器的优先级高?
设置browsers的优先级高于直接设置浏览器的,会覆盖后者。
为什么将modules设置成false,是否还有其他设置方案?
说明其默认为true,默认都是支持commonjs规范的。还可以设置成amd、umd之类的。
transform-runtime解决了一个什么问题?
解决了es6语法中全局对象或者全局对象方法编译不足的情况。
既然transform-runtime只是解决es6,那我要是用es7、es8、es9甚至更高怎么办呢?
babel-polyfill , core-js、regenerator-runtime
为什么不推荐全局安装脚手架?
版本更新迭代太快了,安装在项目本地易升级。
BABEL_ENV或者NODE_ENV的设置方式
# osx|linux
export NODE_ENV=production
#window
SET NODE_ENV=production
Babel的默认行为是什么?
转换了形如let、箭头函数之类的语法, 如果要完全的ES6语法支持需要安装plugin-transform-runtime插件,如果需要更高版本的话,那就需要安装polyfill插件。
参考文献
babel官网:https://babeljs.io/
@babel/preset-env文档:https://babeljs.io/docs/en/babel-preset-env/
@babel/plugin-transform-runtime:https://babeljs.io/docs/en/next/babel-plugin-transform-runtime.html
@babel/cli文档:https://babeljs.io/docs/en/babel-cli
babel配置文件:https://babeljs.io/docs/en/config-files#file-relative-configuration
babel环境变量配置:https://babeljs.io/docs/en/options#envname
@xxx npm包的解释 About Scope: https://docs.npmjs.com/about-scopes

本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。
Babel:下一代Javascript语法编译器的更多相关文章
- 《前端之路》之 Babel 下一代 JavaScript 语法编译器
写本章的内容的出发点主要是 为了对于之前关于 JS 版本的一个总结,在之前的开发中,我们始终对于 ECMAScript 的版本的更新不够重视,以至于在后面的 开发过程中,我们始终会被各种新奇的语法打断 ...
- 用于编写下一代JavaScript的编译器。
下载 用于编写下一代JavaScript的编译器. 支持巴别塔 Babel(发音为babble)是一个由社区驱动的项目,被许多公司和项目使用,由一群志愿者维护.如果你愿意帮助支持这个项目的未来,请考虑 ...
- 一分钟入门 Babel(下一代 JavaScript 语法的编译器)
简单来说把 JavaScript 中 es2015/2016/2017/2046 的新语法转化为 es5,让低端运行环境(如浏览器和 node )能够认识并执行.严格来说,babel 也可以转化为更低 ...
- When Colon Scripting is comming(JavaScript语法扩充)
当冒号脚本来临-- JavaScript语法扩充 连续好几夜的不能安眠,得出结论就是,未来语言未来的编译器应该是支持语法定制规则和语法扩展的,这样使得编程语言不断进化以更利于人类使用!of cours ...
- JavaScript语法对{}的奇葩处理
JavaScript的语法有多坑,算是众人皆知了. 今天看到vczh的这条微博:http://weibo.com/1916825084/B7qUFpOKb , 代码如下: {} + []; [] + ...
- 使用webpack+babel构建ES6语法运行环境
1.前言 由于ES6语法在各个浏览器上支持的情况各不相同,有的浏览器对ES6语法支持度较高,而有的浏览器支持较低,所以为了能够兼容大多数浏览器,我们在使用ES6语法时需要使用babel编译器将代码中的 ...
- JavaScript:JavaScript语法的详细介绍
JavaScript语法:只要Java会了,基本上javascript语法就会了. ——变量的定义 ——程序的结构控制 ——数组操作 ——函数的定义即使用 基本的test.html代码如下,它会导入下 ...
- javascript语法详解
javascript语法:运算符 条件语句if...else... 条件语句switch 循环语句for 循环语句while 跳转语句 js运算符 1.算数运算符:+ - * % / ++ ...
- Javascript语法基础
Javascript语法基础 一.基本数据类型 JavaScript中支持数字.字符串和布尔值三种基本数据类型: 1.数字 数字型是JavaScript中的基本数据类型.在JavaScript ...
随机推荐
- java中Proxy类初探
在java中提供了一个动态代理类,这个类位于java.lang.reflect包中的Proxy类中.什么是动态代理类呢?就是可以在运行时创建一个实现了一组给定接口的新类.听上去有点高深的样子,其实是提 ...
- Mysq数据库索引(B-Tree索引)
一.B-Tree索引的底层结构 所有的值都是按顺序存储的,并且每一个叶子页到根的距离相同,如图所示,B-Tree索引的底层数据结构一般是B+树,反应了MyISAM索引是如何工作的. 二.B-T ...
- visual studio 2005/2010/2013/2015/2017 vc++ c#代码编辑常用快捷键-代码编辑器的展开和折叠
visual studio 2005/2010/2013/2015/2017 vc++ c#代码编辑快捷键-代码编辑器的展开和折叠 VS2015代码编辑器的展开和折叠代码确实很方便和实用.以下是展开代 ...
- 谈谈我对C# 多态的理解
面向对象三要素:封装.继承.多态. 封装和继承,这两个比较好理解,但要理解多态的话,可就稍微有点难度了.今天,我们就来讲讲多态的理解. 我们应该经常会看到面试题目:请谈谈对多态的理解. 其实呢,多态非 ...
- Java对MongoDB的CRUD
https://blog.51cto.com/aiilive/1339058 MongoDB提供的Java操作API可以说是对Mongo数据库命令的Java翻译,熟悉Mongo命令,熟悉Java操作数 ...
- SpringBoot--使用redis实现分布式限流
1.引入依赖 <!-- 默认就内嵌了Tomcat 容器,如需要更换容器也极其简单--> <dependency> <groupId>org.springframew ...
- linux下将多个ts文件合并为一个MP4文件
1. 安装ffmpeg工具 sudo apt install ffmpeg 2. 确保所有ts文件无损坏后,确保当前目录(即存放ts文件的目录)无txt文件及mp4文件,在存放ts文件的目录下建立te ...
- CSS选择器整理以及优先级介绍
一.基础选择器 选择器 名称 描述 兼容性 * 通配选择器 选择所有的元素 ie6+ E 元素选择器 选择指定的元素 ie6+ #idName id选择器 选择id属性等于idName的元素 ie6+ ...
- 感知融合 awesome list
感知融合 awesome list 雷达聚类 雷达处理杂波滤除 CFAR (Constant False Alarm Rate):Lee, Jae-Eun, et al. "Harmonic ...
- CSS3样式_实现字体发光效果
text-shadow 属性仅仅是用来设置文本阴影的,似乎并不能实现字体发光效果.其实不然,这正是 text-shadow 属性的精妙之处.当阴影的水平偏移量和垂直偏移量都为0时,阴影就和文本重合了. ...