1. babel基本概念
简单来说babel是javascript的一个编译器,javascript不断的告诉发展,但是浏览器的发展速度却跟不上。例如es6中增加了箭头函数、块级作用域等新的语法和Symbol、Promise等新的数据类型,部分浏览器并不能马上支持这些新的语法或者方法,所以需要将他们转化成浏览器能够识别的js代码,babel就是来做这部分工作的。
2. 通常我们在webpack配置项目时不仅需要配置babel,还需要使用对应的插件或者polyfill,因为默认情况下babel可以将箭头函数,class等语法转换为ES5兼容的形式,但是却不能转换Map,Set,Promise等新的全局对象以及挂在在全局对象上的方法,这时候就需要使用polyfill去模拟这些新特性。
3.关于babel的配置
① 在配置babel-loader时options里面配置,如下图
② 将上面options对象内容放置在单独的.babelrc文件里面。此文件建议放在根目录下,当然要是没有放在根目录下,构建的时候也会自动的一个文件夹一个文件夹去抓取这个文件。
③ 第三种是命令行的形式,在package.json文件scripts里面配置指令。
④ 在package.json文件中对babel进行配置。添加"babel"这个key值,它也是一个对象和上图options对象里面的内容一样。
以上四种方式推荐第②种,因为写起来比较直白也更容易读懂,配置也方便。第①有个问题就是不会处理<script></script>里面代码不会处理,就会导致例如采用vue开发时,.vue文件里面script里面的代码将不会被编译,所以会有问题。
注: plugins和presets的先后顺序是先plugins处理后presets,其中plugins中的插件是按从前到后的顺序, 而presets是倒着从后往前。
4.前面说了使用babel是必须还要有配套的polyfill,接下来谈谈几种polyifill的方案
接着我们来说两个概念:
转译器: 转译器是一系列插件的集合。(对应配置项presets)比如babel-preset-es2015就包含了transform-es2015-arrow-functions(es2015箭头函数转译插件)、transform-es2015-classes(es2015 class类转译插件)等。仅仅可以处理语法部分的兼容问题。新的API及全局的方法需要借助相关转译插件或polyfill。
转译插件: 转译插件是转译需要用到的插件,比如babel-plugin-transform-decorators-legacy,这个插件只负责装饰器的转译。(对应配置项plugins)
关于polyfill的处理建议以下几种设置:
① 全局使用babel-polyfill(不设置babel-preset-env options项的useBuiltIns)
具体使用方法如下:
a. 直接在index.html文件head中直接引入polyfill js或者CDN地址;
b. 在package.json中添加babel-polyfill依赖, 在webpack配置文件增加入口: 如entry: ["babel-polyfill",'./src/app.js'], polyfill将会被打包进这个入口文件中, 必须放在文件最开始的地方;
c. 在入口文件顶部直接import ''babel-polyfill';
此方案的优点是简单、一次性可以解决浏览器的所有polyfill兼容性问题,缺点就是一次性引入了ES6+的所有polyfill, 打包后的js文件体积会偏大, 在现代浏览器上不需要全部的polyfill,其次污染了全局对象,不太适合框架类的开发,框架类的开发建议下面的②方案。
注: polyfill.io库会根据你的使用的浏览器做相应的polyfill,可以极大的解决引入过大的问题。
② 全局使用babel-polyfill(设置babel-preset-env options项的useBuiltIns)
具体使用方法如下:
1. 引入babel-preset-env包;
2. 在.babelrc文件预设presets中使用设置babel-preset-env options项
useBuiltins: usage | entry
(usage: 仅仅加载代码中用到的 polyfill. entry: 根据浏览器版本的支持,将 polyfill 需求拆分引入,仅引入有浏览器不支持的polyfill)
targets.browsers: 浏览器兼容列表
modules: false
3. 在入口文件顶部直接import ''babel-polyfill';
此方案的适合应用级的开发,babel会根据指定的浏览器兼容列表自动引入所有所需的polyfill。
③ 使用插件 babel-runtime 或 babel-plugin-tranform-runtime
babel-runtime会出现重复引用的问题,而babel-plugin-tranform-runtime抽离了公共模块, 避免了重复引入,下面的配置主要以babel-plugin-tranform-runtime来说。
1. 引入babel-plugin-tranform-runtime包;
2. 在.babelrc文件plugins中添加babel-plugin-tranform-runtime: "plugins": ["transform-runtime"];
3. 配合上面方法②中的第2步中的预设presets的设置;
此方案无全局污染,依赖统一按需引入(polyfill是各个模块共享的), 无重复引入, 无多余引入,适合用来开发库。