babel 是什么?
babel 在前端项目中充当的是一个代码转译工具的角色。
为什么要使用babel ?
我们都知道JS的新的API,语法糖层出不穷,在丰富了我们的知识库的同时,也极大的便利了我们的开发。
但是由于 浏览器的版本标准不一致,尤其是移动端(各个手机有自带的默认浏览器,再加上QQ,UC, 360,百度,夸克)浏览器众多,对我们前端开发的H5页面兼容性未知,当你使用了某个新的API时,有概率会直接在某些小众或者低版本浏览器上报错。
当然,这些浏览器对ES3,ES5的语法肯定能够识别,如果这也不能识别,趁早放弃这款浏览器吧。
天下苦秦久矣,如果能有一款工具能帮我们把高版本语法转化为浏览器可以兼容的低版本语法就好了。
所以,babel 出现了!
当然也可以不用。只要你写的语法版本足够低,没有转译的空间了。
babel 的作用是什么?
转译 = 转化+编译
借助各种插件实现对JS 语法和新的API的转化编译成低版本兼容性更好的代码。
为什么我总是看不懂项目中babe.config.js的配置项?
当然不是你的问题
他的配置项确实很复杂,且网上配置项众说纷纭,花里胡哨一大堆,各个插件名字相似,很容易搞混。
况且,这只是一个工具,配成啥样,都能用,既然能用,凑活用呗。
再者,要写那么多页面,babel配置文件要么早都配置好了,哪有那么多时间折腾研究配置项呢?
但是,我恰好有时间,争取用最简洁的语言说清楚,babel这是个什么玩意。
能达到面试标准即可。
babel.config.js常见的配置项有哪些?
- plugin 插件
- preset 预设好的一堆插件
preset = plugin的集合
可以理解成,转译JS要用到很多插件,所以先人们整理了一批插件做成了插件集合,可以放在preset里直接使用。
压力骤减
还有一些新语法,没有包括在preset的集合中,就需要额外引入plugin
如果你不用,那用不到plugin,如果你用了,就得引入相关plugin
怎么知道用不用plugin,该用哪些plugin呢?
我也不知道,实践出真知
我一般方式是,先用,报错了,再具体分析需要引入哪个插件
比如我在项目中使用了可选链操作符?. 与双问号 ??
其实也不是特别新,但是google 浏览器打开页面直接报错,搜索引擎告诉我需要在babel 中配置两个插件,专门进行解析
配置好,无任何异常报错。
这就说明我们这两个新语法没有在预设的集合中,所以需要额外引入插件
module.exports = { presets: ['@vue/cli-plugin-babel/preset'], plugins: [ // ?? '@babel/plugin-proposal-nullish-coalescing-operator', // 可选链 '@babel/plugin-proposal-optional-chaining', [ 'import', { libraryName: 'vant', libraryDirectory: 'es', style: true }, 'vant' ] ] }
常见的presets有哪些呢
- @babel/preset-env
preset-env 内部集成了大部分我们日常开发需要的插件集合。
- @vue/cli-plugin-babel
一般来说,如果是vue-cli 起的项目,就不需要再额外关系babel的配置了。。
这就是vue-cli特有的babel插件,其中包括babel7,babel-loader,@vue/babel-preset-app 等等
其中也加载了@babel/preset-env,查看./node_modules/@vue/babel-preset-app,其中配置了
presets: [ [require('@babel/preset-env'), { useBuiltIns, corejs: 3 }] ]
当然了还有其他一些的react项目presets 集合,我没见过,所以没有写,欢迎大家补充。
由此可见,babel/preset-env 才是核心,我们需要先掌握核心科技。
babel/preset-env 是什么?
preset-env 集成了大部分的转译插件,会根据配置的参数进行转译
主要参数有两个
- useBuiltIns
- 有三个值 默认false,entry,usage
- 配合 @babel/polyfill 使用,我们先按下不表
- targets
- 用来指定需要支持的浏览器范围
babel/preset-env 的作用是什么?
例如下面一段代码
转换前代码
let array = [1, 2, 3, 4, 5, 6]; array.includes(item => item > 2); new Promise()
转译后代码
var array = [1, 2, 3, 4, 5, 6]; array.includes(function (item) { return item > 2; }); new Promise()
Babel 默认只是转换了 箭头函数 let ,Promise 和 includes 都没有转换 ,这是为什么?
Babel 把 Javascript 语法 分为 syntax 和 api
api 指那些我们可以通过 函数重新覆盖的语法 ,类似 includes,map,includes,Promise。
syntax 像箭头函数,let const class
babel/preset-env 仅仅会转译新的语法,不会处理 ES 新的API 和ES实例方法。
比如
- 全局对象:Promise、WeakMap 等。
- 全局静态函数:Array.from、Object.assign 等。
- 实例方法:比如 Array.prototype.includes 等。
那新的API如何处理呢?
这就是我们下面要提到的polyfill
@babel/polyfill 是什么?
先翻译翻译 polyfill 顾名思义是一种填充材料
业内都叫做 垫片,就是名字,不用刻意去记忆,理解成补充材料就好。
在babel 中就是用来处理上面提到无法处理的api。