
什么是Babel?
在进行讲解之前, 我们先把我们之前的项目精简一下,只留一个index.js,内容如下,
const arr = [
new Promise(() => {}),
new Promise(() => {}),
]
arr.map(item => {
console.log(item)
})
我们在上面使用的ES6的语法,现在对项目进行打包,这里我们不用devServer,因为我们想听过打包,去分析一下/dist/main.js
,这里关于打包的知识就不讲了。我们看main.js
中的最后几行代码,可以看到如下的代码
/*! no static exports found */
/***/ (function(module, exports) {
eval("const arr = [\r\n new Promise(() => {}),\r\n new Promise(() => {}),\r\n]\r\narr.map(item => {\r\n console.log(item)\r\n})//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9zcmMvaW5kZXguanMuanMiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9zcmMvaW5kZXguanM/YjYzNSJdLCJzb3VyY2VzQ29udGVudCI6WyJjb25zdCBhcnIgPSBbXHJcbiAgICBuZXcgUHJvbWlzZSgoKSA9PiB7fSksXHJcbiAgICBuZXcgUHJvbWlzZSgoKSA9PiB7fSksXHJcbl1cclxuYXJyLm1hcChpdGVtID0+IHtcclxuICAgIGNvbnNvbGUubG9nKGl0ZW0pXHJcbn0pIl0sIm1hcHBpbmdzIjoiQUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSIsInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///./src/index.js\n");
/***/ })
可以看到,里面有箭头函数,有const
,有Promise
这些ES6的代码,可以说原封不动的做了打包,实际上这样做事可能存在一些问题的,比如我们在低版本的浏览器中,比如我们在不支持Promise
的浏览器中(IE:别瞅我~),这些代码都会失效,于是我们期望有没有一种技术可以让我们在打包的时候,将这种ES6的语法转成ES5,这样他就能再各种浏览器下运行了,这种技术就是babel。
我们可以进入到babel官网,可以看到哈,如官网所说,Babel 是一个 JavaScript 编译器。我先来从头教大家如何去使用一个babel
- 我们到"设置"中,先来选择一个babel的使用场景,这里我们选择webpack
- 按照指南,我们看到了,设立需要我们去安装
bable-loader
和@babel/core
,大家看到loader
肯定是陌生,这里肯定是为了满足Webapck模块打包的,@babel/core
实际上就是babel
的核心库了。 - 在配置中加一条规则
module: {
rules: [
{ test: /\.js$/, exclude: /node_modules/, loader: "babel-loader" }
]
}
意思是如果我们遇到js代码,我们就只用babel-loader
进行分析。其中exclude
的意思是如果你的js文件是在node_modules
里面,我们就不使用babel-loader
了。因为node_modules
里面的代码都是第三方的代码,我们没必要对第三方的代码进行ES6转ES5的操作。并且这些第三方的模块一般早就给我们做了这一步,我们也没必要重复去做。
- 安装
@babel/preset-env
,实际上,babel-loader
相当于webpack和babel之间的桥梁,只是帮我们把功能打通,要想进行转移,我们还需要借助@babel/preset-env
来帮我们做真正的编译功能,他里面包含了一些翻译规则等...
npm install @babel/preset-env --save-dev
- 修改配置
{
test: /\.js$/,
exclude: /node_modules/,
loader: "babel-loader",
options: {
presets: ["@babel/preset-env"]
}
}
接下来,让我们打包试一下看看是不是ES6语法标称了ES5,当然,结果肯定是~ :)
但是我们会发现,这里的Promise
其实还是不被IE浏览器支持的,这里我们会使用@babel/polyfill
来兼容低版本浏览器。
使用@babel/polyfill兼容低版本浏览器
我们到babel官网的文档中,找到@babel/polyfill
,然后做出相应的配置。
- 安装
npm install --save @babel/polyfill
- 使用
将@babel/polyfill
应用到业务代码最顶端
import "@babel/polyfill";
const arr = [
new Promise(() => {}),
new Promise(() => {}),
]
arr.map(item => {
console.log(item)
})
这时候我们打包试一下,我们会发现一个问题,main.js体积暴增。我这边已经达到了900多kb,这多的内容就是@babel/polyfill
在弥补低版本浏览器一些内容,自己做了一些实现。然后把他们注入进main.js。包括一些我们并没有在项目中用到的一些语法,只注入我们用到的就可以了,那么我们该如何去优化这一点呢?
我们需要对babel-loader
的配置改成下面这样
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader',
options: {
presets: [['@babel/preset-env', {
useBuiltIns: 'usage'
}]]
}
}
这时候,再打包,你会发现,main.js小了不少呢,并且也可以在低版本浏览器下运行了。
当然了,关于babel-loader
的presets我们还可以写一些其他内容,这里我们找到一个官网的配置,写进去,
options: {
presets: [['@babel/preset-env', {
targets: {
"edge": "17",
"firefox": "60",
"chrome": "67",
"safari": "11.1",
},
useBuiltIns: 'usage'
}]]
}
上面新加入的配置的意思是,项目运行的浏览器版本环境,用来决定对于JS转译的需求,比如下面的配置
targets: {
"chrome": "67",
},
意思是@babel/preset-env
会根据你规定的浏览器版本去转译,如果67版本对于ES6的兼容很好了,没必要去转了,他就不去注入那些方法了。再重新打包你会发现,main.js又回到了几十kb,在main.js中也没有去转译ES5。
对于babel,其内容有太多太多,甚至比webpack的层次还深,这里不做太多的介绍了,有需求可以去官网看相关配置或者百度~~
你可能不需要@babel/polyfill
这里我们讲了一整篇的babel,其实对于babel有时候并不能按照我们本文讲的情况来配置,比如我们在封装一个组件库的时候,假如像我们上面那样的引入,会造成全局变量的污染,下面我们介绍另外一种方式。(照着官网说明配置即可,这是补充内容,不讲太详细)
@babel/plugin-transform-runtime
- 安装
npm install --save-dev @babel/plugin-transform-runtime
npm install --save @babel/runtime
npm install --save @babel/runtime-corejs2
- 配置
首先注释掉之前index.js中对于@babel/polyfill
的引入,然后替换之前的配置如下
options: {
// presets: [['@babel/preset-env', {
// targets: {
// "chrome": "67",
// },
// useBuiltIns: 'usage'
// }]]
"plugins": [["@babel/plugin-transform-runtime", {
"corejs": 2,
"helpers": true,
"regenerator": true,
"useESModules": false,
}]]
}
这时候打包试试,也是可以正常打包的,这里我们这么做可以避免@babel/polyfill
对于全局变量的污染,当然,如果我们是写业务代码,那就使用@babel/polyfill
就可以满足了。这种方式用来开发组件库使用是个很好的解决方案。
你可能需要创建一个.babelrc的文件
我们发现,babel的配置项的内容非常的多,要是做比较详细的配置的话,其配置内容也是相当的多,这里我们可以用一个.babelrc
的文件来将这些配置分离出来,我们在项目的根目录下新建这个文件。然后将options的内容拿出去就可以了。
写在最后
本篇的内容我们讲解了babel
,可以发现其内容相当多,概念相当多,但其实好多配置是固定的,常用的配置就是几种,大家记住本文这些常用的就行了,感兴趣扩展的可以自己再去扩展。
网友评论