Babel

Babel

Babel 是一个非常强大的 JavaScript 编译器,主要用于将采用 ES2015+ 语法编写的代码转化为向后兼容的低版本 JavaScript 代码(如 ES5),以确保代码能够在当前和旧版本的浏览器或其它环境中运行。

Babel的强大之处在于它的插件(plugins)和预设(Presets)机制,通过不同的插件,开发者可以有针对性地处理某些语法特性。

插件和预设

Babel 本身只是一个 JavaScript 编译器,它不会自动转译代码,转译工作主要是通过插件和预设完成的。每个 Babel 插件负责处理特定的语法或语言特性,比如箭头函数、模版字符串、解构赋值等。

插件(Plugins)

插件是 Babel 的核心功能单位,每个插件负责转换特定的语法特性。例如,有的插件负责转换箭头函数,有的负责转换模板字符串。通过组合不同的插件,Babel 可以实现对各种 JavaScript 语法的支持。 示例:

1// babel.config.js
2module.exports = {
3  plugins: [
4    "@babel/plugin-transform-arrow-functions",
5    "@babel/plugin-transform-template-literals"
6  ]
7}

在这个配置中,@babel/plugin-transform-arrow-functions 插件将箭头函数转换为普通的函数表达式,而 @babel/plugin-transform-template-literals 插件则将模板字符串转换为普通的字符串连接。

预设(Presets)

预设是一组 Babel 插件的集合,通常用于编译特定版本的 JavaScript。例如,@babel/preset-env 是一个非常常用的预设,它根据目标环境自动选择所需的插件来编译代码。 示例:

1// babel.config.js
2module.exports = {
3  presets: ["@babel/preset-env"],
4}

在这个配置中,@babel/preset-env 预设会根据浏览器或运行环境的支持情况,自动添加必要的插件来编译代码。

插件和预设的区别

  • 插件:是用于转换特定语法特性的单独功能单元,可以根据需要单独配置和使用。
  • 预设:是插件的集合,用于简化配置,通常针对特定的 JavaScript 版本或功能集。

转换过程

Babel 的工作流程

首先将源代码解析成 AST,然后使用各种插件对生成的 AST 进行修改已实现特定的功能,比如语法降级,最后,Babel 将修改后的 AST 转换回 JavaScript 代码。

  1. 解析(Parsing)
    • Babel首先将代码解析成抽象语法树(AST),这个过程类似于浏览器的JavaScript引擎解析代码的方式
    • AST 是代码的结构化表示,便于后续的分析和转换。
  2. 转换(Transformation)
    • 根据插件和预设的配置,Babel会对AST进行遍历并修改,将不兼容的语法转换为兼容的语法。例如,将箭头函数转换为普通函数表达式。
  3. 生成(Generation)
  • 最后,Babel将修改后的AST重新生成为 JavaScript 代码。生成的代码是经过转换后可以在目标环境中运行的代码。 以箭头函数的转换为例,Babel首先识别出箭头函数的语法特点,然后通过插件将其转换为等价的普通函数表达式,最后输出转换后的代码。

babel 和 polyfill

需要注意的是,babel只能转译语法,它不会为新的 API 提供 Polyfill,例如:ES6的 promise、Map等API无法通过Babel转换,如果需要支持这些API,需要结合 core-jsregenerator-runtime 等库来实现 Poyfill。 使用 Polyfill 的方法

  • 手动引入:可以手动在项目中引入 core-jsregenerator-runtime 来支持所需的 API。

  • 自动引入:通过配置 Babel 的 @babel/preset-env,可以根据代码中使用的特性自动按需引入 Polyfill。 通过结合使用 Babel 的语法转换和 Polyfill,可以确保现代 JavaScript 代码在旧浏览器和环境中的兼容性。

语法降级

🎯

Babel 可以将 ES2015+ 语法的 JavaScript 代码编译为能在当前浏览器上工作的代码


步骤 1:项目初始化 首先,使用以下命令初始化一个新的项目:

1pnpm init

步骤 2:安装 Babel 依赖 在终端中运行以下命令,安装 Babel 及其所需的包:

  • @babel/core: Babel 的核心库。
  • @babel/cli: Babel 的命令行工具。
  • @babel/preset-env: 一个智能预设,用于编译现代 JavaScript 语法。
1pnpm add -D @babel/core @babel/cli @babel/preset-env

步骤 3:配置 Babel 在项目的根目录下创建一个名为 babel.config.js 的配置文件,并添加以下内容:

1// 配置,基于 commonjs 规范
2// 这个配置文件告诉 Babel 使用 @babel/preset-env 预设来处理代码。
3module.exports = {
4 presets: ["@babel/preset-env"],
5}

步骤 4:编写测试文件src 目录下新建一个 test.js 文件,内容如下:

1// 这个文件包含一个简单的箭头函数用于测试。
2const fn = () => {
3  console.log('test')
4}

步骤 5:添加构建命令package.json 文件中添加一个构建命令,以便使用 Babel 编译代码:

  • src: 源代码目录。
  • --out-dir lib: 指定编译后的代码输出到 lib 目录。
1{
2  "scripts": {
3    "build": "babel src --out-dir lib"
4  }
5}

步骤 6: 运行构建 最后,运行以下命令进行构建:

1pnpm run build

这将使用 Babel 编译 src 目录下的代码,并将结果输出到 lib 目录。

ts转换

🎯

Babel 可以删除类型注释!使用 Babel 将 TypeScript 代码转换为 JavaScript,务必牢记 Babel 不做类型检查


步骤 1:安装依赖 首先,安装用于处理 TypeScript 的 Babel 预设 @babel/preset-typescript

  • @babel/preset-typescript: 用于编译 TypeScript 代码。
1pnpm add -D @babel/preset-typescript

步骤 2:配置 Babel 在项目的根目录下,创建或修改 babel.config.js 文件,以支持 TypeScript。配置如下:

1// 使用 CommonJS 规范导出配置
2module.exports = {
3  presets: ['@babel/preset-env', '@babel/preset-typescript']
4}

步骤 3:创建 TypeScript 文件src 目录下创建一个名为 example.ts 的文件,内容如下:

1const greet = (name: string): string => {
2  return `Hello, ${name}!`;
3}
4console.log(greet('World'));

步骤 4:添加构建命令package.json 文件中添加一个构建命令,以便使用 Babel 编译 TypeScript 代码:

  • --extensions '.ts,.tsx': 指定 Babel 处理 .ts.tsx 文件。
  • --out-dir lib: 指定编译后的代码输出到 lib 目录。
1{
2  "scripts": {
3    "build": "babel src --extensions '.ts,.tsx' --out-dir lib"
4  }
5}

步骤 5:运行构建 最后,运行以下命令进行构建:

1pnpm run build

这将使用 Babel 编译 src 目录下的 TypeScript 文件,并将结果输出到 lib 目录。通过这种方式,您可以将 TypeScript 代码转换为浏览器可以理解的 JavaScript 代码。

jsx 与 react

🎯

使用 Babel 来处理 JSX 语法和 React 代码。


步骤 1:安装 Babel React 预设 为了让 Babel 识别和转换 JSX 语法,我们需要安装 @babel/preset-react

  • @babel/preset-react: 用于编译 JSX 语法和 React 代码。
1pnpm add -D @babel/preset-react

步骤 2:配置babel 在项目的根目录下,修改 babel.config.js 文件以包含 React 预设。配置如下:

1// 配置,基于 commonjs 规范
2module.exports = {
3  presets: ['@babel/preset-env','@babel/preset-react']
4}

步骤 3:创建 React 组件src 目录下创建一个名为 App.jsx 的文件,内容如下:

1import react from 'react'
2import { createRoot } from 'react-dom/client'
3const App = () => {
4    return <div>Code Better</div>
5}
6createRoot(document.getElementById('root')).render(<App />)

步骤 4:运行构建 最后,运行以下命令进行构建:

1pnpm run build

这将使用 Babel 编译包含 JSX 语法的 App.jsx 文件,并输出到指定目录。通过这种方式,您可以将 React 组件转换为浏览器可以理解的 JavaScript 代码。

Polyfill

虽然 Babel 本身不直接提供 Polyfill,但通过配置 @babel/preset-env 和使用 core-js,可以按需引入 Polyfill,以支持不被旧环境原生支持的 JavaScript 新特性。 Polyfill 可以让不支持某些现代 JavaScript 特性的旧浏览器或环境能够运行使用这些特性的代码。例如,PromiseArray.includes 等特性在较旧的浏览器中可能不被支持,通过 Polyfill 可以实现这些功能。 :::tip @babel/preset-env 和 Polyfill 是用于不同目的的工具,它们在现代 JavaScript 开发中可以互补使用。 @babel/preset-env 的作用

  • 语法转换@babel/preset-env 主要负责将现代 JavaScript 语法(例如箭头函数、类、解构赋值等)转换为旧版本 JavaScript 语法,使其能够在不支持这些语法的浏览器中运行。
  • 不转换内置对象:虽然 @babel/preset-env 可以处理语法转换,但它不处理 JavaScript 内置对象和方法的支持问题。例如,它不会自动为 PromiseArray.includesString.padStart 等提供实现。

Polyfill 的作用

  • 提供功能实现:Polyfill 用于在不支持某些内置对象、方法或 API 的环境中提供这些功能的实现。例如,Polyfill 可以为 PromisefetchMap 等提供支持。
  • 补充语法转换:即使语法被转换为旧版本的 JavaScript,代码中使用的某些新特性(如 Promise)仍然需要在运行时环境中得到支持,这就是 Polyfill 的作用。 :::

步骤 1:安装 首先,安装 Babel 及其相关的 Polyfill 包:

  • core-js: 一个模块化的标准库,提供对 ECMAScript 新特性和其他标准库的 Polyfill 支持。
  • regenerator-runtime:用于支持 async/await 和生成器函数的 Polyfill。
1pnpm add core-js

步骤 2:配置 Babel 在项目的根目录下,创建或修改 babel.config.js 文件,以支持 Polyfill。配置如下:

  • useBuiltIns: 'usage': 根据代码中使用的特性按需引入 Polyfill。
  • corejs: 3: 指定使用 core-js 的版本 3。
1// 使用 CommonJS 规范导出配置
2module.exports = {
3  presets: [
4    ['@babel/preset-env', {
5      useBuiltIns: 'usage', // 按需引入 Polyfill
6      corejs: 3 // 使用 core-js 版本 3
7    }]
8  ]
9}

步骤 3:创建示例文件src 目录下创建一个名为 example.js 的文件,内容如下:

1// Promise: 现代 JavaScript 中的异步处理。
2const promiseExample = new Promise((resolve) => {
3  setTimeout(() => resolve('Hello, World!'), 1000);
4});
5promiseExample.then(console.log);
6// Array.includes: 用于检查数组中是否包含某个元素。
7const arrayExample = [1, 2, 3].includes(2);
8console.log(arrayExample);

步骤 4:添加构建命令package.json 文件中添加一个构建命令,以便使用 Babel 编译代码:

1{
2  "scripts": {
3    "build": "babel src --out-dir lib"
4  }
5}

步骤 5:运行构建 最后,运行以下命令进行构建:

1pnpm run build

这将使用 Babel 编译 src 目录下的代码,并根据需要自动引入 Polyfill,以便在旧浏览器中运行。通过这种方式,您可以确保现代 JavaScript 特性在不支持这些特性的浏览器中也能正常工作。