了解babel 7

670 阅读4分钟

babel能做什么

语法转换

转换和编译esnext的语法,甚至是只属于自己的定制化的语法

在目标环境中添加缺失的特性

主要是通过在目标环境注入补丁代码,所以安装的时候是--save。 babel7.0之前的版本安装babel-polyfill,babel7之后的版本安装@babel/polyfill。

但是,@babel/polyfill目前只包含tc39的Stage4阶段的特性,根本无法满足小伙伴们的高超的编码手法,好在babel提供了预设功能,可以配置化的引入代码。

babel是如何工作的

babel是通过babel核心代码+babel插件来工作的

1.核心代码

在这个npm包里@babel/core

使用编码的方式可以直观的看到这个过程,看看打印出来是什么?

const babel =require("@babel/core");
const code=`(n)=>n**2`
const result=babel.transform(code,{
  presets:["@babel/preset-env"]
})
console.log(result.code);

没错就是编译后的代码

2.插件(plugins)

插件文档

Babel 是一个编译器(输入源码 => 输出编译后的代码)。就像其他编译器一样,编译过程分为三个阶段:解析、转换和打印输出。

现在,Babel 虽然开箱即用,但是什么动作都不做。它基本上类似于 const babel = code => code; ,将代码解析之后再输出同样的代码。如果想要 Babel 做一些实际的工作,就需要为其添加插件。

一句话概述就是 插件机制提供了babel的语法解析和代码转换的功能。

!插件是有序执行的,所以在配置中,顺序是很重要的

3.预设(presets)

presets文档

顾名思义就是一份预先设置好的babel配置,里面有presets和plugins。

preset-env里最终输出的是一个配置对象:{plugins:Array}里面只有插件数组

!预设是反序执行的(主要是为了兼容以前用户的常规写法),所以在配置中要特别注意

如何使用babel

1.安装依赖

  1. @babel/core babel核心代码
  2. @babel/cli 这样会在node_modules里的.bin项目中添加了一个叫babel的可执行脚本
  3. @babel/preset-env babel常用的预设

2.添加执行脚本

// package.json
...
scripts:{
  babel:"babel index.js -o compiled.js", //单文件
  babel-lib:"babel src -d lib" //多文件
  //[cli更多选项](https://www.babeljs.cn/docs/babel-cli)
}
...

3.babel常规配置

因为babel的功能主要是通过插件来实现的,所以如果不做任何配置的话,相当于不执行任何插件,也就不做任何处理,所以我们写一份配置文件来让babel变的实用,当然也可以在脚本上添加参数,不过通常在项目中,实用babel配置文件更为直观

babel.config.js

// babel.config.js
module.exports = {
  // presets 生效顺序是倒序的
  presets: [
    [
      "@babel/preset-env",
      {
        // 如果配置,会覆盖browserslist配置,推荐使用browserslist,这样postcss以及其他工具共同使用一份配置
        // targets: {
        // "chrome": "58", 编译后的语法最低支持到chrome 58
        // "esmodules": true 目标为支持es6模块的浏览器环境
        // "node": true // 目标代码为当前node最新版本的标准
        // },
        // 按需自动引入corejs@3的polyfill,entry是全局引入
        useBuiltIns: "usage",
        // 需安装生产依赖core-js@3和regenerator-runtime
        corejs: "3", // 当使用usage参数时,必须指定corejs版本,默认corejs@2,所以这里配置3,生产依赖需要安装core-js@3
      }]
  ],
  // plugins 生效顺序是正序的
  plugins: [
    // 打包后的代码,辅助函数统一从@babel/runtime里引入,可减少重复的helper代码
    // 需要同时安装生产依赖@babel/runtime才能生效
    ["@babel/plugin-transform-runtime"]
  ]
};

.eslintrc.js

// .eslintrc.js
module.exports = {
  // lint环境
  env: {
    es6: true,
    node: true,
  },
  // 扩展规则
  extends: ["airbnb-base"],
  // 解析器
  parser: "@babel/eslint-parser", // 配合babel使用
  parserOptions: {
    ecmaVersion: 12, //es12版本
    sourceType: "module", // default script
    ecmaFeatures: {
      jsx:true,
      impliedStrict: true,
    },
  },
  // 自定义规则 0关闭,1警告,2错误
  rules: {
  },
};

package.json

// package.json
{
  ...
  "scripts": {
    ...
    "babel": "babel src -d lib",
  },
  "devDependencies": {
    ...
    "@babel/cli": "^7.12.1",
    "@babel/core": "^7.12.3",
    "@babel/node": "^7.12.6", // 建议全局安装
    "@babel/plugin-transform-runtime": "^7.12.1",
    "@babel/preset-env": "^7.12.1",
  },
  "dependencies": {
    ...
    "@babel/runtime": "^7.12.5",
    "core-js": "^3.8.0",
    "regenerator-runtime": "^0.13.7"
  },
  // https://caniuse.com/ 可以查看各浏览器支持度
  "browserslist": [
    "> 1%", //全球超过1%人数使用的浏览器
    "last 2 versions",// 所有浏览器兼容到最近的两个版本
    "not ie <= 8"// ie版本不低于8
  ]
}

依赖的用途

开发依赖(--save-dev)

  1. @babel/corebabel核心库
  2. @babel/cli babel命令行
  3. @babel/preset-env babel预设环境,包括已经稳定实现的es6及以上语法插件,当然还有常用的预设@babel/preset-react@babel/preset-typescript
  4. @babel/plugin-transform-runtime 抽取babel辅助函数为公共runtime,减少重复代码
  5. @babel/node 转化es6语法为node支持的语法,推荐全局安装
  6. babel/eslint-parser 配合eslint使用,不然eslint识别不了超前的es语法

生产依赖(--save)

  1. corejs@3 polyfill的代码,建议使用corejs 3.0版本
  2. regenerator-runtime 生成器语法的依赖
  3. @babel/runtime 这个是配合@babel/plugin-transform-runtime使用的

编写babel插件

可以跟着这篇文章来写一个自己的插件插件开发手册传送门-英语

中文版比较滞后,大家酌情阅读插件开发手册传送门-中文

参考