1.脚手架@babel/cli
babel
作为一门转换工具。它自带了一套自己的脚手架工具。
新建一个项目,执行:
yarn add @babel/cli -D
TIP
从 babel@7.0
版本开始,babel
会将它所有的官方包都放在 @babel
这个命名空间下。其实这并不是 babel
的特例。而是 npm
对于它自身包管理的一种优化。 babel
只是顺道遵守了而已。
这样的话,我们就可以使用 babel
命令行。由于环境变量的原因,所以我们配置下 package.json
(你也可以利用 npx
取代这种方式)。利用 npm
来执行 babel
:
{
"scripts": {
"compiler": "babel './src/main.js' --out-dir dist"
}
}
当执行 yarn compiler
时,按照道理来说,babel
就会将 src
目录下的 main.js
,转译到 dist
目录中。
但现在执行 yarn compiler
后,会发现 dist/main.js
文件中的代码并没有任何转换迹象。
2.核心库@babel/core
babel
的核心功能包含在 @babel/core
模块中。安装:
yarn add @babel/core -D
这时执行 yarn compiler
, 代码仍然不会转换。
可以将 @babel/core
理解成一个核心转换模块函数,它的执行依赖于 options
配置。如果没有 options
,那么这个函数什么也不会做。
function core (code, options = []) {
options.forEach(item => {
code += item
})
return code
}
而这些 options
在 babel
中对应的就是 plugins
。
3.插件plugins
安装下转换箭头函数的插件:
yarn add @babel/plugin-transform-arrow-functions -D
在 package.json
中的 scripts
添加命令:
{
"scripts": {
"compiler:plugin": "babel './src/main.js' --out-dir dist --plugins=@babel/plugin-transform-arrow-functions"
}
}
再次执行 yarn compiler:plugin
,会发现 main.js
中的箭头已被转换:
var _this = this;
// 1.arrow function
const arrowFun = function () {
console.log('arrow-function', _this);
};
4.预设presets
presets
其实就是一组 plugins
的集合。官方提供的预设有四组:
@babel/preset-env
@babel/preset-flow
@babel/preset-react
@babel/preset-typescript
其中 @babel/preset-env
代表的是对于环境 environment
的预设。现在我们使用 --presets
来代替上面使用的 --plugins
。
{
"scripts": {
"compiler:preset": "babel './src/main.js' --out-dir dist --presets=@babel/preset-env"
}
}
执行 yarn compiler:preset
。会发现代码已经被转换成ES5
代码(除了需要@babel/polyfill
的语法。如promise
等。)
另外直接执行转译过后的代码,会有报错 ReferenceError: regeneratorRuntime is not defined
。这是因为 async await
的实际运行也需要 @babel/polyfill
。
具体代码可见下方。
TIP
在未指定浏览器目标的情况下,@babel/preset-env
会将所有 ES2015-ES2020
代码转换为与ES5兼容。 但是不建议以这种方式使用 @babel/preset-env
,因为它没有利用针对特定环境/版本的功能。
"use strict";
var _this = void 0;
function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }
function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
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); return Constructor; }
// 1.arrow function
var arrowFun = function arrowFun() {
console.log('arrow-function', _this);
};
// 2.class
var Person = /*#__PURE__*/function () {
function Person() {
_classCallCheck(this, Person);
this.name = name;
}
_createClass(Person, [{
key: "say",
value: function say() {
alert('hello');
}
}]);
return Person;
}();
// 3.promise es6新增
var promise = new Promise(function (resolve, reject) {
setTimeout(function () {
if (Math.random() * 10 >= 5) {
resolve('大于5');
} else {
reject('小于5');
}
}, 2000);
});
// 4.async await es7
function fn() {
return _fn.apply(this, arguments);
}
function _fn() {
_fn = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee() {
var result;
return regeneratorRuntime.wrap(function _callee$(_context) {
while (1) {
switch (_context.prev = _context.next) {
case 0:
_context.prev = 0;
_context.next = 3;
return promise;
case 3:
result = _context.sent;
console.log(result);
_context.next = 10;
break;
case 7:
_context.prev = 7;
_context.t0 = _context["catch"](0);
console.warn('error', _context.t0);
case 10:
console.log('--- after promise ---');
case 11:
case "end":
return _context.stop();
}
}
}, _callee, null, [[0, 7]]);
}));
return _fn.apply(this, arguments);
}
fn();
// 5.includes
var flag = [1, 2, 3].includes(1);
console.log('includes', flag);
5.总结
这一章,主要来了解快速使用 babel
需要安装什么。
@babel/cli
, 官方脚手架。@babel/core
, 核心转换模块。@babel/plugins
或者@babel/presets
, 具体的转换规则。@babel/polyfill
, 低版本浏览器需要腻子。不过babel
已经有新的使用方法来弥补@babel/polyfill
存在的缺点。
后面我们会循序渐进的来深入了解。