Skip to content

一、介绍

Babel 是一个工具链,主要用于将采用 ECMAScript 2015+ 语法编写的代码转换为向后兼容的 JavaScript 语法,以便能够运行在当前和旧版本的浏览器或其他环境中。下面🌰就是 Babel 为你做的其中一点点事情:

js
// Babel 接收到的输入是: ES2015 箭头函数
[1, 2, 3].map(n => n + 1);

// Babel 输出: ES5 语法实现的同等功能
[1, 2, 3].map(function(n) {
  return n + 1;
});

Babel 通过语法转换器来支持新版本的 JavaScript 语法。babel 里面你的插件 让你现在就能使用新的语法,无需等待浏览器的支持。下图示例:

babel的作用通过上面图你就知道了,将新语法、高级语法代码转换为浏览器都能识别的代码。我们通过实战开发来学习。

二、搭建环境

js
新建文件夹,npm init -y

安装babel所需的包

js
// npm
npm install --save-dev @babel/core @babel/cli @babel/preset-env
// yarn
yarn add --dev @babel/core @babel/cli @babel/preset-env

@babel/core: 是使用Bable进行转码的核心npm包,我们使用的babel-cli、babel-node都依赖这个包.

@babel/cli: Babel 自带了一个内置的 CLI 命令行工具,可通过命令行编译文件。此外,各种可直接调用脚本都存放在 @babel/cli/bin 中。一个可通过 shell 执行的实用脚本 - babel-external-helpers.js,以及 Babel cli 主脚本 babel.js。

@babel/preset-env: 只对我们所使用的并且目标浏览器中缺失的功能进行代码转换和加载 polyfill。

三、配置

新建babel.config.js

js
const presets = [
  [
    "@babel/preset-env",
    {
      targets: {
        edge: "17",
        firefox: "60",
        chrome: "67",
        safari: "11.1",
      },
      useBuiltIns: "usage",
      corejs: "3.6.4",
    },
  ],
];

module.exports = { presets };

大概意思就是将代码转换为目标浏览器对应版本的代码。useBuiltIns的作用是,因为polyfill里面有有大量的方法、新的内置组件等会添加到全局范围(global scope)和类似 String 这样的原生原型(native prototypes)中。刚好preset 提供了一个 "useBuiltIns" 参数,当此参数设置为 "usage" 时,就会加载上面所提到的最后一个优化措施,也就是只包含你所需要的 polyfill。

三、babel第一个转译程序

新建build.js

js
// /build.js
const babel = require('@babel/core');

const code = `
const sayHi = () =>{
    console.log("Hello Babel")
}
sayHi()
`
const optionObject = {

}
const result = babel.transform(code, optionObject);
console.log(result.code)

终端:

js
./node_modules/.bin/babel build.js --out-dir dist
// or
./node_modules/.bin/babel build.js -d dist
// or
./npx babel build.js -d dist

你可以利用 npm@5.2.0 所自带的 npm 包运行器将 ./node_modules/.bin/babel 命令缩短为 npx babel

执行完命令之后:

js
"use strict";

var babel = require('@babel/core');
var code = "\nconst sayHi = () =>{\n    console.log(\"Hello Babel\")\n}\nsayHi()\n";
var optionObject = {};
var result = babel.transform(code, optionObject);
console.log(result.code);

在用node执行转移后的代码,看看转移后的code。

js
node dist/build.js

得到

js
"use strict";

const sayHi = () => {
  console.log("Hello Babel");
};
sayHi();

会发现,es6剪头函数并没有转译,这是为什么??

其实是babel配置的问题。因为babei只会转移目标浏览器对应版本的代码,因为上面浏览器版本已经支持了ES6剪头函数,所以它就不需要再转换了,如果把上面配置的浏览器版本改一下。那就不一样了。

js
const presets = [
  [
    "@babel/preset-env",
    {
      targets: {
        edge: "17",
        firefox: "60",
---     chrome: "67",
+++     chrome: "37",
        safari: "11.1",
      },
      useBuiltIns: "usage",
      corejs: "3.6.4",
    },
  ],
];

module.exports = { presets };

把chrome浏览器版本降低之后,再来打包试试。

js
npx babel build.js --out-dir dist

node dist/build.js
js
"use strict";

var sayHi = function sayHi() {
  console.log("Hello Babel");
};
sayHi();

因为当前代码片段只涉及了剪头函数,其实是可以使用官方的其他插件(@babel/plugin-transform-arrow-functions),因为它只关注这个的转移。为什么我们直接使用preset-env,是他都包含了这些加载所需的转换插件能力。不用考虑太多,不过它挺大的。这个也就是和按需引入和直接全部引入一个意思。

到这里我们就学会了babel转译的第一个程序!