[1] babel的使用

86 阅读3分钟

一、作用

Babel 是一个JS转译器,主要用于将 ECMAScript 2015(EA6)+ 版本的代码转换为向后兼容的 JavaScript (ES5)语法,以便能够运行在当前和旧版本的浏览器或其他环境中。

二、运行

babel 总共分为三个阶段:解析,转换,生成。

注意:

babel 本身不具有任何转化功能,它把转化的功能都分解到一个个 plugin 里面。

因此当我们不配置任何插件时,经过 babel 的代码和输入是相同的。

插件总共分为两种:

语法插件:解析这一步就使得 babel 能够解析特定的语法 。

转译插件:转换这一步把源码转换并输出。这也是我们使用 babel 最本质的需求。

同一类语法可能同时存在语法插件版本和转译插件版本。如果我们使用了转译插件,就不用再使用语法插件了。 转换插件将启用相应的语法插件,因此你不必同时指定这两种插件。

三、几个重要包

工具作用
core-js转换一些内置类 (Promise, Symbols等等) 和静态方法 (Array.from 等)。绝大部分转换是这里做的。自动引入。
regenerator作为 core-js 的拾遗补漏,主要是 generator/yield 和 async/await 两组的支持。当代码中有使用 generators/async 时自动引入。
helpers如上面的 asyncToGenerator 就是其中之一,其他还有如 jsx, classCallCheck 等等,可以查看 babel-helpers。在代码中有内置的 helpers 使用时(如上面的第一段代码)移除定义,并插入引用(于是就变成了第二段代码)。

四、配置文件

Babel的配置文件就是.babelrc,存放在根目录下。

使用Babel的第一步,就是配置这个文件,该文件是用来设置【预设】(组合好的一套插件,让你不需要一个一个的去按照插件了)和【插件】(具体的插件)的。

{
  "presets": [
     // 带了配置项,自己变成数组
    ["env", {  // 第一个元素依然是名字,第二个元素是对象,列出配置项。
      "modules": false,
      "targets": {
        "browsers": ["> 1%", "last 2 versions", "not ie <= 8"]
      }
    }],
    // 不带配置项,直接列出名字
    "stage-2"
  ],
  "plugins": ["transform-runtime", "transform-vue-jsx"]
}

运行顺序:

  • Plugin 先运行,从前到后顺序执行。
  • Preset后执行,从后到前顺序执行。

插件和 preset 的配置项:

简略情况下,插件和 preset 只要列出字符串格式的名字即可。

但如果某个 preset 或者插件需要一些配置项(或者说参数),就需要把自己先变成数组。第一个元素依然是字符串,表示自己的名字;第二个元素是一个对象,即配置对象。

4.1 presets

babel 还提供了一组插件的集合-presets,免去一次开发者一个个添加并安装。

因为常用,所以不必重复定义 & 安装。(单点和套餐的差别,套餐省下了巨多的时间和配置的精力)

常用环境编写了一些 preset:

image.png

env

因为 env 最为常用也最重要,所以我们有必要重点关注。 env 的核心目的是通过配置得知目标环境的特点,然后只做必要的转换。

例如目标浏览器支持 es2015,那么 es2015 这个 preset 其实是不需要的,于是代码就可以小一点(一般转化后的代码总是更长),构建时间也可以缩短一些。

如果不写任何配置项,env 等价于 latest,也等价于 es2015 + es2016 + es2017 三个相加(不包含 stage-x 中的插件)。

下面列出几种比较常用的配置方法:

{
  "presets": [
    ["env", {
      "targets": {
        "browsers": ["last 2 versions", "safari >= 7"]
      }
    }]
  ]
}

如上配置将考虑所有浏览器的最新2个版本(safari大于等于7.0的版本)的特性,将必要的代码进行转换。而这些版本已有的功能就不进行转化了。

这里的语法可以参考 browserslist

另外一个有用的配置项是 modules。它的取值可以是 amd, umd, systemjs, commonjs 和 false。这可以让 babel 以特定的模块化格式来输出代码。如果选择 false 就不进行模块化处理。

五、babel-loader

一些大型的项目都会有构建工具 (如 webpack 或 rollup) 来进行代码构建和压缩 (uglify)。

理论上来说,我们也可以对压缩后的代码进行 babel 处理,但那会非常慢。因此如果在 uglify 之前就加入 babel 处理,岂不完美?

在webpack中使用babel-loader

所以就有了 babel 插入到构建工具内部这样的需求。 以 webpack 为例,webpack 有 loader 的概念,因此就出现了 babel-loader。

和 babel-cli 一样,babel-loader 也会读取 .babelrc 或者 package.json 中的 babel 段作为自己的配置,之后的内核处理也是相同。唯一比 babel-cli 复杂的是,它需要和 webpack 交互,因此需要在 webpack 这边进行配置。比较常见的如下:

module: {
  rules: [
    {
      test: /.[ejt]s$/,
      use: ['cache-loader','babel-loader'],
      exclude: /node_modules/
    },
  ]
}

// 遇到JS文件就先用babel-loader处理。
可以这样理解babel-loader:

相当于一个交通枢纽,只是在webpack打包时遇到js,ts文件,交给babel去处理,

至于怎么处理,就跟webpack就没有关系了,跟babel配置有关。babel通过babelrc里面配置的内容去处理js,ts文件。