1.脚手架@babel/cli
babel 作为一门转换工具。它自带了一套自己的脚手架工具。
新建一个项目,执行:
yarn add @babel/cli -DTIP
从 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存在的缺点。
后面我们会循序渐进的来深入了解。