1 概述
babel编译工具,这是前端工程三大工具中最简单的一个了,分别是npm包管理工具,webpack构建工具和babel编译工具。
babel是将es6代码转换为es5代码,抹平了不同浏览器环境的差异问题。
2 编译与运行
2.1 文件编译
babel src/add.js --out-file lib/add.js
babel对单个文件进行编译
2.2 目录编译
babel src --out-dir lib
babel对单个文件进行编译
2.3 脚本编译
var babel = require("babel-core");
const { readdirSync , writeFileSync } = require('fs');
const { join } = require('path');
const cwd = __dirname
function getSrc(){
const files = readdirSync(join(cwd, 'src'));
return files;
}
function transform(file){
const srcFile = join(cwd, 'src',file)
const destFile = join(cwd, 'es',file)
const data = babel.transformFileSync(srcFile,{
presets:[
['env',{modules:false}]
],
babelrc:false,
})
writeFileSync(destFile,data.code,'utf-8');
}
const src = getSrc();
for( const i in src ){
transform(src[i])
}
引入babel-core,用自己喜欢的方式来编译指定的文件,并且可以输入特定的babel选项,并且不受.babelrc的限制。这个方法常用于开发库时建立不同的babel编译输出。
2.4 直接运行
babel-node src/index.js
使用babel-node,就能直接运行es6代码,而不需要编译。
2.5 注册运行
node src/index_es6.js
require('babel-register');
require('./index');
使用babel-register,建立一个hook处理所有require的输入,将文件实时转换为es5代码,这个方法跟babel-node一样,只是它可以用node来直接启动。
3 选项
{
presets:['env','react','stage-0']
}
指定.babelrc中的presets,指定输出的环境,可以注意到,env的presets的选项很多,可以指定输出的浏览器版本,以及是否转换es6的modules输出等等。
4 插件
{
presets:['env','stage-0'],
plugins:["transform-runtime"]
}
指定transform-runtime的作为plugins,这个plugins相当有用。
import add from './add';
const delay = (timeout)=>{
return new Promise((resolve,reject)=>{
setTimeout(resolve,timeout);
})
}
class App{
async go(){
await delay(1000);
let result = add(3,4);
console.log(result);
}
}
const app = new App();
app.go();
这是原来的es6代码
'use strict';
var _regenerator = require('babel-runtime/regenerator');
var _regenerator2 = _interopRequireDefault(_regenerator);
var _asyncToGenerator2 = require('babel-runtime/helpers/asyncToGenerator');
var _asyncToGenerator3 = _interopRequireDefault(_asyncToGenerator2);
var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck');
var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
var _createClass2 = require('babel-runtime/helpers/createClass');
var _createClass3 = _interopRequireDefault(_createClass2);
var _promise = require('babel-runtime/core-js/promise');
var _promise2 = _interopRequireDefault(_promise);
var _add = require('./add');
var _add2 = _interopRequireDefault(_add);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var delay = function delay(timeout) {
return new _promise2.default(function (resolve, reject) {
setTimeout(resolve, timeout);
});
};
var App = function () {
function App() {
(0, _classCallCheck3.default)(this, App);
}
(0, _createClass3.default)(App, [{
key: 'go',
value: function () {
var _ref = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee() {
var result;
return _regenerator2.default.wrap(function _callee$(_context) {
while (1) {
switch (_context.prev = _context.next) {
case 0:
_context.next = 2;
return delay(1000);
case 2:
result = (0, _add2.default)(3, 4);
console.log(result);
case 4:
case 'end':
return _context.stop();
}
}
}, _callee, this);
}));
function go() {
return _ref.apply(this, arguments);
}
return go;
}()
}]);
return App;
}();
var app = new App();
app.go();
这是输出后的代码,要注意的是,transform-runtime会做两个事
- 转换语法,像ES6 Class会引入helper中的createClass函数来辅助实现
- 特性垫片,由于浏览器中的差异,并不是所有浏览器都支持完整的promise特性,babel会引入core-js中的promise来辅助实现async/await。要注意的是,这种polyfill的方法是不影响全局作用域的,它只在本地作用域中有效。
对比加和不加transform-runtime,区别在于:
- 不加transform-runtime,意味着createClass这些操作都会在本模块内部直接展开实现,导致每个模块中都会出现相同的样本代码,导致模块太大。
- 加transform,意味着createClass这些操作只会在本模块内import进来,实现统一由babel-runtime/helpers来完成,大大减少了模块大小。
对比babel-transform-runtime和babel-polyfill,区别在于:
- babel-polyfill是全局垫片,一旦加入后,全局都能使用,不仅仅在本模块,但是一旦引入后,意味着Map,Set,Promise等所有垫片都全部加入,不管有没有用到。
- babel-transform-runtime是局部垫片,只在模块内部有效,而且,用到那些就加那些,不会增多。
所以,在写工具库或者项目时,尽可能只使用babel-transform-runtime,而不要使用babel-polyfill。这样打包出来的程序更小,而且不会污染全局作用域。
5 总结
babel还是比较简单的
参考资料:
- 本文作者: fishedee
- 版权声明: 本博客所有文章均采用 CC BY-NC-SA 3.0 CN 许可协议,转载必须注明出处!