最重要的还是Babel的配置

Start

为什么我们需要Babel来转译?

js作为一种宿主语言,依赖执行的环境(浏览器、node等),不同环境对js语法的支持不尽相同,特别是ES6之后,ECMAScrip对版本的更新已经到了一年一次的节奏,当我们想使用这些激动人心的新语法时,却又担心浏览器环境并不支持新语法,那怎么办呢?
babel的出现就是为了解决这个问题,把那些使用新标准编写的代码转译为当前环境可运行的代码,简单点说就是把ES6代码转译到ES5。

认识ES新规范

JavaScript语言是集万千开发者共同维护的语言,当你有什么新的idea,你可以向他们组织提出你的想法,从提出想法到正式列入语言规范会经历很多步骤,当然时间也是很久的,假如你想使用哪些还没列入规范的新语法,就要用到babel来转译,我们来看看具体是哪几个阶段:

被纳入到ES标准的语法必须要经过如下五个阶段:

  1. Stage 0: strawman
  2. Stage 1: proposal
  3. Stage 2: draft - 必须包含2个实验性的具体实现,其中一个可以是用转译器实现的,例如Babel。
  4. Stage 3: candidate - 至少要有2个符合规范的具体实现。
  5. Stage 4: finished

一般当到达了Stage 2后,我们就能用babel来转译这项新的语法,用到实际开发当中。

Webpack配置步骤

依赖安装

1
2
3
4
5
6
npm install
babel-loader
babel-core
babel-preset-env
babel-plugin-transform-runtime
-D

我们安装前,来分别了解一下这些依赖都是有什么作用

  • babel-loader

作为webpack的loader的一种,作用同其他loader一样,实现对特定文件类型的处理,也就是去处理.js文件

  • babel-core

babel-core是作为babel的核心存在,babel的核心api都在这个模块里面,当webpack使用babel-loader处理文件时,babel-loader实际上调用了babel-core的api

  • babel-preset-env

babel有几种规则都可以实现对ES6语法的转码,如babel-preset-es2015、babel-preset-es2016、babel-preset-es2017,不过官方现已建议采用babel-preset-env,为什么会这样呢?

我们首先要了解到,ES6发布在2015年,距离现在3年了,很多浏览器已经支持了很大一部分ES6语法,这些浏览器是能够识别ES6语法的,而babel-preset-es2015是将所有ES6语法全部转译为ES5,这就导致一个问题:打包文件过大。

那么babel-preset-env给我们带来什么好处呢?他能够按照我们自定义规则,让你指定一个环境且仅仅转译在那个环境中缺少的特性,怎么理解呢?假如我们只需要适配安卓7.0的移动端web浏览器,这个时候,我们只需要找到安卓7.0中不支持的语法(一小部分),将这部分代码转译为ES5即可,就不必将所有的代码一把梭地转译为ES5,具体配置我们下面会详细说明。

  • babel-plugin-transform-runtime

首先babel基础包(不安装额外东西)并不是支持完整的新规范语言,当我们在项目中用到哪些新的语法,那么就会从transform-runtime来获取到他的转译源码。

配置webpack.config.js

这里我们选择使用babel-loader来处理.js文件,我们只需要在rule加上:

1
2
3
4
5
6
7
8
9
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader',
},
...
}

配置.babelrc文件

当然我们也可以直接在webpack.config.js文件里面配置这些规则,我们在根目录文件下添加.babelrc文件:

1
2
3
4
5
6
{
"presets": [
"env"
],
"plugins": ["transform-runtime"]
}

这样我们就简单的配置完了一个babel配置,但是在没有任何配置选项的情况下,babel-preset-env 与 babel-preset-latest(或者babel-preset-es2015,babel-preset-es2016和babel-preset-es2017一起)的行为完全相同。也就是相当于这样:

1
2
3
4
5
6
7
8
{
"presets": [
"es2015",
"es2016",
"es2017",
],
"plugins": ["transform-runtime"]
}

这样岂不是还是将所有的代码打包成ES5?所以我们需要自己配置babel-env:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{
"presets": [
["env", {
"targets": { //指定要转译到哪个环境
//浏览器环境,这里要适配现在浏览器的前两个版本,以及safari大于7的版本
"browsers": ["last 2 versions", "safari >= 7"]
},
"modules": "commonjs", //使用commonjs的modules规范
"debug": true, // 开启env的debug,这样我们在控制台能够看到详细的env信息
"include": ["transform-es2015-arrow-functions"], //强制开启某些模块,默认为[]
"exclude": ["transform-es2015-for-of"] //禁用某些模块,默认为[]
}]
],
"plugins": ["transform-runtime"]
}

以上配置就能满足大部分开发了,具体配置还需要去官网查看详细的说明: Babel

试一试

配置完所有的选项后,我们在index.js试一试使用新的语法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import './index.css'
import './test.js'

console.log('222')
class App {
constructor(name, age) {
this.name = name
this.age = age
}
}
const a1 = new App('vince', 15)
console.log(a1.age)
async function test() {
console.log('async')
}
test()
if (module.hot) {
// 实现热更新
module.hot.accept()
}

运行npm run dev后便能看到控制台打印了正确的信息,以及用import正确引入了文件。

Last

这一章节我们了解到了Babel的一些基本知识,以及配置了可以满足大部分开发需求的Babel,请关注后续Webpack的博文。

本章节的代码已经上传到Github,传送门webpack-study,请自行切换到chapter-04分支。