babel编译工具

2018-06-02 fishedee 前端

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还是比较简单的

参考资料:

相关文章