[聚合文章] Babel 配置技巧

JavaScript 2018-01-16 22 阅读

当下,每个写 JavaScript 的猿可能都在或多或少地使用 Babel。借助 Babel,我们可以使用最新的 ECMAScript 特性,而不用太关注浏览器支持。Babel 在背后进行了许多复杂的转换,我们要做的,就是写配置文件,告诉 Babel 我们想要什么。下面就来看看一些配置技巧吧。

在 .babelrc 中使用 JS

All Babel API options except the callbacks are allowed (because .babelrc files are serialized as JSON5 ).

Babel 使用 JSON5 解析 .babelrc ,也就是说可以在 .babelrc 中使用宽松的语法,可以添加注释什么的,不过,真的可以像 ESLint 的 .eslintrc.js 直接使用 JS 配置吗?截止目前的最新版本(Babel 6),并不会解析 .babelrc.js 之类的文件,不过可以变通一下。

首先,建一个 .babelrc.js 文件:

const ES = process.env.BABEL_ENV === 'es'

module.exports = {
  presets: [
    [
      'env', { modules: !ES }
    ],
    'react',
    'stage-2',
  ],
};

接下来,再建一个 Babel 认识的 .babelrc 文件:

{
  "presets": ["./.babelrc.js"]
}

或者,嫌多一个文件麻烦的话,加在 package.json 里面也没问题:

{
  "babel": {
    "presets": [
      "./.babelrc.js"
    ]
  }
}

通过 JS 编写配置文件,不仅可以给一些参数复杂的插件传递正则、函数等参数,还可以根据环境变量设置不同的参数,产出不同的代码。

减少冗余代码

babel-plugin-transform-runtime

以下面的源代码为例:

class Person {
  constructor(options) {
    this.options = Object.assign({}, Person.DEAULTS, options);
  }

  sayHi() {
    return `Hi, this is ${this.options.name}`;
  }
}

Person.DEAULTS = {
  name: 'anonymous',
};

.babelrc 配置为:

{
  "presets": [
    "es2015"
  ],
  "plugins": ["transform-object-assign"]
}

转换后的代码为:

'use strict';

var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };

var _createClass = 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); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

var Person = function () {
  function Person(options) {
    _classCallCheck(this, Person);

    this.options = _extends({}, Person.DEAULTS, options);
  }

  _createClass(Person, [{
    key: 'sayHi',
    value: function sayHi() {
      return 'Hi, this is ' + this.options.name;
    }
  }]);

  return Person;
}();

Person.DEAULTS = {
  name: 'anonymous'
};

就是说,如果源代码中有 10 个类似的模块,就会有 10 份重复的 _extends 、 _createClass 、 _classCallCheck 代码分布在各个文件中,太多冗余。通过 babel-plugin-transform-runtime 可以有效解决这一问题。

安装并配置 Runtime transform 插件:

{
  "presets": [
    "es2015"
  ],
  "plugins": [
    "transform-object-assign",
    "transform-runtime"
  ]
}

转换出来的代码会引用公共的模块,干净多了:

'use strict';

var _extends2 = require('babel-runtime/helpers/extends');

var _extends3 = _interopRequireDefault(_extends2);

var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck');

var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);

var _createClass2 = require('babel-runtime/helpers/createClass');

var _createClass3 = _interopRequireDefault(_createClass2);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

var Person = function () {
  function Person(options) {
    (0, _classCallCheck3.default)(this, Person);

    this.options = (0, _extends3.default)({}, Person.DEAULTS, options);
  }

  (0, _createClass3.default)(Person, [{
    key: 'sayHi',
    value: function sayHi() {
      return 'Hi, this is ' + this.options.name;
    }
  }]);
  return Person;
}();

Person.DEAULTS = {
  name: 'anonymous'
};

记得把 babel-runtime 也加到依赖中。如果需进一步定制,可 参考官方文档 。

生产环境中移除 React PropTypes 定义

React PropTypes 定义可以在开发时帮助我们校验传入的属性,但在构建生产环境代码时,完全可以移除,以减小文件体积,节省宽带。 babel-plugin-transform-react-remove-prop-types 就是干这事的,具体参见文档,不再赘述。

注:本文内容来自互联网,旨在为开发者提供分享、交流的平台。如有涉及文章版权等事宜,请你联系站长进行处理。