Babel是一个Javascript的编译器,经过它你能够将一些新版本的ECMAScript语法转换成低版本的语法。以便可以在低版本的浏览器或者其它环境平稳运行。html
截至目前笔者写这篇文章的时候,babel的版本是7.10.0node
mkdir babel-study && cd babel-study
linux
npm init -y
ios
npm i @babel/cli @babel/core @babel/preset-env --save-dev
git
相关依赖包说明:es6
@babel/cli: hello,你好,我是脚手架工具,我能够经过一些命令将源文件编译成目标代码。github
@babel/core: hello,你好,我是一个代码分析选手,我负责将代码分析称ast,方便其余插件进行相关处理。chrome
@babel/preset-env: hello,你好,我是一个语法转义器,我负责的内容是将JS的相关语法进行编译,关于转义新增的API和全局对象这个我不负责的。npm
楼下这几位就是经常使用的babel配置参数了,这里作简要介绍数组
早期的版本实际上是引入相似babel-preset-x
,这种形式的包,如今官方推荐统一用@babel/preset-env
,这个包来作语法转义器这部分的工做。
弥补babel自己上的功能不足,好比转义新增的API和全局对象可能就须要用到一些新的插件来作这部分工做,咱们称之为补丁转义器。
把不须要babel编译的文件写配置到这个参数里面,是一个数组的形式。
Boolean类型的,将其设置为true后,编译后的文件会被压缩。
Boolean类型的,将其设置为true后,编译后的文件会有注释(你项目开发中写的注释)。
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 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-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
将高版本的JS语法转换成低版本的JS语法,可兼容不一样版本的浏览器或者运行环境,划重点,解决了代码在不一样版本的浏览器的兼容性问题。人的脑容量都是有限的,兼容的事情就愉快地交给它吧。
首先,这绝对不是为了装逼,也不是为了混淆代码。咱们先思考下使用高版本的语法它有什么用?有一些实际上是低版本的语法糖,使用了这些咱们能够减小代码量,而后减轻维护成本。可是ECMAScript它是一个语法标准,不一样的JS引擎以及浏览器对它的实现和支持又不大同样,全部咱们不可以保证使用高版本的语法它可以完美在各平台运行,这也就是babel的做用体现。
早期地预设有babel-preset-es201五、babel-preset-stage-x之类的啥的,如今官方推荐统一@babel/preset-env,脚手架统一@babel/cli,对,不成文地规定就是@babel打头基本是对的,polyfill除外。
先说结论,用前者@babel/xxx, @xxx就至关于注册了一个命名空间,特指这个是xxx下的某包,它是一个范围,是一种组织的体现形式,例如@ataola/zjt,
若是只是建立一个.babelrc里面什么都不写,会报错,由于babel会读取里面的格式,加个{}
,这个是能够运行的,里面什么都不写。这里思考下babel的默认行为是什么?只是转换了Javascript的语法,而不对新的API进行转换,新的仍是要用插件的。
在presets里的形如@babel/preset-env就是语法转义器,在plugins下的插件包就是补丁转义器,它们的分工不一样,前者是将相关语法进行编译,后者弥补了前者的一些不足,故称之为补丁。
设置browsers的优先级高于直接设置浏览器的,会覆盖后者。
说明其默认为true,默认都是支持commonjs规范的。还能够设置成amd、umd之类的。
解决了es6语法中全局对象或者全局对象方法编译不足的状况。
babel-polyfill , core-js、regenerator-runtime
版本更新迭代太快了,安装在项目本地易升级。
# osx|linux export NODE_ENV=production #window SET NODE_ENV=production
转换了形如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 国际许可协议进行许可。