babel之配置文件.babelrc入门详解


Posted in Javascript onFebruary 22, 2018

介绍

es6特性浏览器还没有全部支持,但是使用es6是大势所趋,所以babel应运而生,用来将es6代码转换成浏览器能够识别的代码
babel有提供专门的命令行工具方便转码,可以自行去了解

什么是Babel

官方解释,是下一代JavaScript 语法的编译器。

既然是下一代Javascript的标准,浏览器因版本的不同对此会有兼容性问题,JavaScript的新的方法都不能使用,但是目前我们在项目开发一直提倡使用最新的语法糖编写,不但能减少代码量,而且async,await等新特性还解决了回调的编写机制,减轻了代码维护成本。

Babel就因此而生,它可以让你放心使用大部分的JavaScript的新的标准的方法,然后编译成兼容绝大多数的主流浏览器的代码。在项目工程脚手架中,一般会使用.babelrc文件,通过配置一些参数配合webpack进行打包压缩。也通过网上了解,写法各有不同,参数也大不相同,因此,我重新整理一份资料,详细的介绍下各个配置项的意义所在,以便清晰了解如果使用。

以下配置主要正对webpack3+写法。

Babel转译器

在.babelrc配置文件中,主要是对预设(presets)和插件(plugins)进行配置,因此不同的转译器作用不同的配置项,大致可分为以下三项:

1.语法转义器。主要对javascript最新的语法糖进行编译,并不负责转译javascript新增的api和全局对象。例如let/const就可以被编译,而includes/Object.assign等并不能被编译。常用到的转译器包有,babel-preset-env、babel-preset-es2015、babel-preset-es2016、babel-preset-es2017、babel-preset-latest等。在实际开发中可以只选用babel-preset-env来代替余下的,但是还需要配上javascirpt的制作规范一起使用,同时也是官方推荐

{
 "presets": ["env", {
   "modules": false
  }],
  "stage-2"
}

2.补丁转义器。主要负责转译javascript新增的api和全局对象,例如babel-plugin-transform-runtime这个插件能够编译Object.assign,同时也可以引入babel-polyfill进一步对includes这类用法保证在浏览器的兼容性。Object.assign 会被编译成以下代码:

__WEBPACK_IMPORTED_MODULE_1_babel_runtime_core_js_object_assign___default()

3.jsx和flow插件,这类转译器用来转译JSX语法和移除类型声明的,使用Rect的时候你将用到它,转译器名称为babel-preset-react

创建预设(presets)

主要通过npm安装babel-preset-xx插件来配合使用,例如通过 npm install babel-preset-stage-2 babel-preset-env --save-dev 安装,会有相应如下配置。

{
 "presets": [
  ["env", options],
  "stage-2"
 ]
}

stage-2配置

babel主要提供以下几种转义器包,括号里面是对应配置文件的配置项

babel-preset-stage-0(stage-0) 
babel-preset-stage-1(stage-1) 
babel-preset-stage-2(stage-2) 
babel-preset-stage-3(stage-3)

不同阶段的转译器之间是包含的关系,preset-stage-0转译器除了包含了preset-stage-1的所有功能还增加了transform-do-expressions插件和transform-function-bind插件,同样preset-stage-1转译器除了包含preset-stage-2的全部功能外还增加了一些额外的功能。

options配置介绍

官方推荐使用babel-preset-env来替代一些插件包的安装(es2015-arrow-functions,es2015-block-scoped-functions等等),并且有如下几种配置信息,介绍几个常用的,

更多配置可以参考官网https://babeljs.io/docs/plugins/preset-env/

{
  "targets": {
    "chrome": 52,
    "browsers": ["last 2 versions", "safari 7"],
    "node":"6.10"
  }
  "modules": false
}

targets可以制定兼容浏览器版本,如果设置了browsers,那么就会覆盖targets原本对浏览器的限制配置。

targets.node正对node版本进行编译

modules通常都会设置为false,因为默认都是支持CommonJS规范,同时还有其他配置参数:"amd" | "umd" | "systemjs" | "commonjs",systemjs我还不知道规范写法是什么,amd和umd以及commonjs相对比较熟悉,下面简要列举下书写规范。

amd代码规范,在ng1中会用到比较多,主要用于依赖注入:

define(['jquery'], function ($) {
  //  方法
  function myFunc(){};
 
  //  暴露公共方法
  return myFunc;
})

commonjs规范,也是node环境中尊崇的一种规范:

var $ = require('jquery');
//  方法
function myFunc(){};
 
//  暴露公共方法(一个)
module.exports = myFunc;
{% endcodeblock %}
>umd规范,兼容amd以及commonjs规范,目前在第三方插件编写使用比较多:
{% codeblock lang:javascript %}
(function (root, factory) {
  if (typeof define === 'function' && define.amd) {
    // AMD
    define(['jquery'], factory);
  } else if (typeof exports === 'object') {
    // Node, CommonJS之类的
    module.exports = factory(require('jquery'));
  } else {
    // 浏览器全局变量(root 即 window)
    root.returnExports = factory(root.jQuery);
  }
}(this, function ($) {
  //  方法
  function myFunc(){};
 
  //  暴露公共方法
  return myFunc;
}));

插件(plugins)

插件配置项同预设配置项一样,需要搭配babel相应的插件进行配置,可以选择配置插件来满足单个需求,例如早期我们会有如下配置:

{
 "plugins": [
  "check-es2015-constants",
  "es2015-arrow-functions",
  "es2015-block-scoped-functions",
  // ...
 ]
}

但是这些插件从维护到书写极为麻烦,后来官方统一推荐使用env,全部替代了这些单一的插件功能,可以简化配置如下,也就是我前面提到了babel-preset-env:

{
 "presets": [
  "es2015"
 ]
}

这里主要介绍两款常用插件,分别是babel-plugin-transform-runtime,babel-plugin-syntax-dynamic-import。

基本配置代码如下:

{
 "plugins": [
  "syntax-dynamic-import",["transform-runtime"]
 ]
}

transform-runtime

为了解决这种全局对象或者全局对象方法编译不足的情况,才出现了transform-runtime这个插件,但是它只会对es6的语法进行转换,而不会对新api进行转换。如果需要转换新api,也可以通过使用babel-polyfill来规避兼容性问题。

对Object.assign进行编译,配置与未配置经过webpack编译后的代码片段如下:

// 未设置代码片段:
__webpack_require__("ez/6");
var aaa = 1;

function fna() {
 var dd = 33333;
 var cc = Object.assign({ key: 2 });
 var xx = String.prototype.repeat.call('b', 3);
 if ("foobar".String.prototype.includes("foo")) {
  var vv = 1;
 }

 return dd;
}
// 设置代码片段:
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_babel_runtime_core_js_object_assign___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_babel_runtime_core_js_object_assign__);

__webpack_require__("ez/6");
var aaa = 1;

function fna() {
 var dd = 33333;
 var cc = __WEBPACK_IMPORTED_MODULE_1_babel_runtime_core_js_object_assign___default()({ key: 2 });
 var xx = String.prototype.repeat.call('b', 3);
 if ("foobar".String.prototype.includes("foo")) {
  var vv = 1;
 }

 return dd;
}

对class定义类会进行编译,配置与未配置经过webpack编译后的代码片段如下:

// 未设置代码片段:
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

var Canvas = function Canvas(height, width) {
 _classCallCheck(this, Canvas);

 this.height = height;
 this.width = width;
};

var Canvas2 = function Canvas2(height, width) {
 _classCallCheck(this, Canvas2);

 this.height = height;
 this.width = width;
};
// 设置代码片段:
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_babel_runtime_helpers_classCallCheck___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_babel_runtime_helpers_classCallCheck__);

var Canvas = function Canvas(height, width) {
 __WEBPACK_IMPORTED_MODULE_0_babel_runtime_helpers_classCallCheck___default()(this, Canvas);

 this.height = height;
 this.width = width;
};

var Canvas2 = function Canvas2(height, width) {
 __WEBPACK_IMPORTED_MODULE_0_babel_runtime_helpers_classCallCheck___default()(this, Canvas2);

 this.height = height;
 this.width = width;
};

对Generator函数也有同上的编译效果,目前项目中使用该函数较小,一般使用promise替代,以及async await所以未对该函数做测试。

官方说对promise也会产生编译,但是实际测试结果却没有效果

经过webpack打包最终测试,引入transform-runtime该配置项后,打包入口js文件大小会略微增大,并不像官方说的能够缩小文件体积

未配置的最终打包效果:

babel之配置文件.babelrc入门详解

配置后的最终打包效果:

babel之配置文件.babelrc入门详解

虽然文件大小会有所增大,但是解决一些兼容性的问题,同时,从以上给出的测试代码例子来看,使用transform-runtime后,可以减少内部全局函数的定义,从结构上看尊崇了webpack的模块化思想,所以还是建议使用该插件。

syntax-dynamic-import

这个插件主要解决动态引入模块的问题

function nDate() {
 import('moment').then(function(moment) {
  console.log(moment().format());
 }).catch(function(err) {
  console.log('Failed to load moment', err);
 });
}
nDate();

如果.babelrc配置项中使用了"stage-2",也可以不实用该插件,同样支持动态模块引入。

不然就会报以下错误:

  1. Module build failed: SyntaxError: 'import' and 'export' may only appear at the top level, or (import 和 export只能在最外层,也就是不能用在函数或者块中)
  2. Module build failed: SyntaxError: Unexpected token, expected {

其他配置项

ignore

主要作用就是可以指定不编译那些代码

{
 "ignore":["./module/a.js"]
}

let,Object.assign,class定义都未编译,编译效果如下:

__webpack_require__("ez/6");
const aaa = 1;

function fna () {
 let dd = 33333
 let cc = Object.assign({key:2})
 let xx = String.prototype.repeat.call('b', 3)
 if ("foobar".String.prototype.includes("foo")) {
  let vv = 1
 }

 return dd
}

function fna2 () {
 return fna() + aaa + __WEBPACK_IMPORTED_MODULE_0__b__["a" /* default */]
}

class Canvas {
 constructor(height, width) {
  this.height = height;
  this.width = width;
 }
}

class Canvas2 {
 constructor(height, width) {
  this.height = height;
  this.width = width;
 }
}

minified

主要设置编译后是否是压缩,boolean类型,如果使用babel-cli进行打包编译文件这个配置项能够起到作用,但是目前大部分还是会依赖第三方打包工具,例如webpack,所以这个配置参数一般不用设置,webpack插件中的UglifyJsPlugin做了压缩的工作。

comments

在生成的文件中,不产生注释,boolean类型,webpack插件中的UglifyJsPlugin也同样集成了这个功能。

env

基本配置如下:

{
 "env": {
  // test 是提前设置的环境变量,如果没有设置BABEL_ENV则使用NODE_ENV,如果都没有设置默认就是development
  "test": {
   "presets": ["env", "stage-2"],
   // instanbul是一个用来测试转码后代码的工具
   "plugins": ["istanbul"]
  }
 }
}

再谈兼容性问题

Babel默认只转换新的JavaScript语法,而不转换新的API,比如Iterator、Generator、Set、Maps、Promise等等全局对象,以及一些定义在全局对象上的方法(比如Object.assign)都不会转码,具体的可以参考babel-plugin-transform-runtime模块的 definitions.js 文件。

这里主要涉及到babel编译后依然会存在浏览器兼容性问题,一般会使用transform-runtime和babel-polyfill配合使用,对于后者只需要在项目入口文件require引入即可。

当然在使用类似Object.assign函数功能时,可以使用lodash库来替代,promise可以使用Q.js替代等等方案,这样依赖可以不需要引入以上插件,具体可以根据项目具体安排

总结

.babelrc配置文件主要还是以presets和plugins组成,通过和webpack配合进行使用,分享下我们在项目中常用的配置。以上都是通过学习总结出来的,有什么不对的地方希望指出。

vue项目开发使用的配置如下:

{
 "presets": [
  ["env", {
   "modules": false
  }],
  "stage-2"
 ],
 // 下面指的是在生成的文件中,不产生注释
 "comments": false,
 "plugins": ["transform-runtime","syntax-dynamic-import"],
 "env": {
  // test 是提前设置的环境变量,如果没有设置BABEL_ENV则使用NODE_ENV,如果都没有设置默认就是development
  "test": {
   "presets": ["env", "stage-2"],
   // instanbul是一个用来测试转码后代码的工具
   "plugins": ["istanbul"]
  }
 }
}

react项目开发使用的配置如下:

{
 "presets": [
  ["env", { "modules": false }],
  "stage-2",
  "react"
 ],
 "plugins": ["transform-runtime"],
 "comments": false,
 "env": {
  "test": {
   "presets": ["env", "stage-2"],
   "plugins": [ "istanbul" ]
  }
 }
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
推荐30个新鲜出炉的精美 jQuery 效果
Mar 26 Javascript
使用jQuery fancybox插件打造一个实用的数据传输模态弹出窗体
Jan 15 Javascript
javascript图片相似度算法实现 js实现直方图和向量算法
Jan 14 Javascript
jQuery实现转动随机数抽奖效果的方法
May 21 Javascript
JavaScript中的Object对象学习教程
May 20 Javascript
微信公众号 摇一摇周边功能开发
Dec 08 Javascript
Bootstrap实现各种进度条样式详解
Apr 13 Javascript
jQuery实现base64前台加密解密功能详解
Aug 29 jQuery
JS实现手写parseInt的方法示例
Sep 24 Javascript
javascript中函数的写法实例代码详解
Oct 28 Javascript
使用vuex存储用户信息到localStorage的实例
Nov 11 Javascript
TensorFlow.js 微信小程序插件开始支持模型缓存的方法
Feb 21 Javascript
javascript填充默认头像方法
Feb 22 #Javascript
一次记住JavaScript的6个正则表达式方法
Feb 22 #Javascript
利用CDN加速react webpack打包后的文件详解
Feb 22 #Javascript
node内置调试方法总结
Feb 22 #Javascript
详解vue移动端日期选择组件
Feb 22 #Javascript
webpack 单独打包指定JS文件的方法
Feb 22 #Javascript
webpack中使用iconfont字体图标的方法
Feb 22 #Javascript
You might like
php FLEA中二叉树数组的遍历输出
2012/09/26 PHP
PHP动态生成指定大小随机图片的方法
2016/03/25 PHP
php实现购物车产品删除功能(2)
2020/07/23 PHP
jQuery cdn使用介绍
2013/05/08 Javascript
js实现瀑布流的一种简单方法实例分享
2013/11/04 Javascript
利用Jquery实现可多选的下拉框
2014/02/21 Javascript
JS 打印界面的CSS居中代码适用所有浏览器
2014/03/19 Javascript
jQuery中:image选择器用法实例
2015/01/03 Javascript
js文本框输入内容智能提示效果
2015/12/02 Javascript
JavaScript Split()方法
2015/12/18 Javascript
一步一步封装自己的HtmlHelper组件BootstrapHelper(二)
2016/09/14 Javascript
js上下视差滚动简单实现代码
2017/03/07 Javascript
使用JS中的Replace()方法遇到的问题小结
2017/10/20 Javascript
vue中实现移动端的scroll滚动方法
2018/03/03 Javascript
浅谈vue-cli 3.0.x 初体验
2018/04/11 Javascript
vue实现点击关注后及时更新列表功能
2018/06/26 Javascript
Vue render函数实战之实现tabs选项卡组件
2019/04/22 Javascript
详解如何给React-Router添加路由页面切换时的过渡动画
2019/04/25 Javascript
layui实现左侧菜单点击右侧内容区显示
2019/07/26 Javascript
javascript 代码是如何被压缩的示例代码
2020/05/06 Javascript
js实现弹幕飞机效果
2020/08/27 Javascript
python的几种开发工具介绍
2007/03/07 Python
详解Python中的相对导入和绝对导入
2017/01/06 Python
对python当中不在本路径的py文件的引用详解
2018/12/15 Python
Python操作rabbitMQ的示例代码
2019/03/19 Python
Python语法之精妙的十个知识点(装B语法)
2020/01/18 Python
前端面试必备之html5的新特性
2017/09/05 HTML / CSS
H5页面适配iPhoneX(就是那么简单)
2019/12/02 HTML / CSS
html5视频自动横过来自适应页面且点击播放功能的实现
2020/06/03 HTML / CSS
李维斯牛仔裤英国官方网站:Levi’s英国
2019/10/10 全球购物
投标担保书范文
2014/04/02 职场文书
机关作风整顿个人剖析材料
2014/10/06 职场文书
工程部主管岗位职责
2015/02/12 职场文书
nginx限制并发连接请求数的方法
2021/04/01 Servers
项目中Nginx多级代理是如何获取客户端的真实IP地址
2022/05/30 Servers
ECharts transform数据转换和dataZoom在项目中使用
2022/12/24 Javascript