Jacky's blog Jacky's blog
首页
  • 编码专题
  • 深入浅出 Vite
  • 深入浅出 babel
  • 快速上手API
  • 深入浅出 react
  • Node

    • code-notebook
  • 状态管理

    • redux
  • 前端工程化

    • Wepack
  • React源码

    • React源码
  • 组件库封装

    • 组件库
  • 开发工具

    • Vscode 插件
  • 项目展示
  • 案例中心 (opens new window)
  • First Project
  • 基础算法题
  • 链表题
  • 动态规划
  • 双指针
  • 递归
  • 数据结构
  • 前端学习计划 (opens new window)
  • 技术随笔
  • 转载文章
  • 包管理工具
  • 前端学习周报
  • VSCode插件
  • Promise 专题
  • 函数技巧
  • React 专题
  • 配置文件

    • TSCONFIG-配置 (opens new window)
    • NGINX-配置 (opens new window)
    • 正则规则查询手册 (opens new window)
    • Lint 配置 (opens new window)
  • 教程

    • GIT-教程
    • NPM SCRIPTS-工作流 (opens new window)
    • DOCKER-教程 (opens new window)
    • LERNA-教程 (opens new window)
    • GIT-常用操作整理 (opens new window)
  • VSCode

    • LAUNCH.JSON (opens new window)
  • 指令

    • NPM 指令 (opens new window)
    • NVM 指令 (opens new window)
    • Nginx 指令 (opens new window)
    • YARN 指令 (opens new window)
    • PNPM 指令 (opens new window)
  • 库

    • FS-EXTRA 库 (opens new window)
    • NODE 库-PATH (opens new window)
  • 永远的神

    • 魔法师卡颂-自顶向下学 React 源码 (opens new window)
    • 全栈潇晨 (opens new window)
    • 博客-程序员山月-Daily (opens new window)
    • 淘系前端:冴羽 (opens new window)
  • 系列文章

    • 《图解HTTP》 (opens new window)
    • 《ES6标准入门》 (opens new window)
    • 《现代JavaScript教程》 (opens new window)
    • 《深入浅出Webpack》 (opens new window)
    • VSCode 插件系列:小茗同学 (opens new window)
    • JEST 教程 (opens new window)
    • 前端精读周刊:各种精读系列 (opens new window)
    • 一文吃透系列 (opens new window)
    • 图解 REACT 原理 (opens new window)
  • 实用网站

    • MDN (opens new window)
    • CAN I USE (opens new window)
    • TYPESCRIPT-ESLint-RULES (opens new window)
    • ESLint-RULES (opens new window)
    • FRONT-END TREND (opens new window)
    • NPM TREND (opens new window)
    • 在线分析 Node 依赖 (opens new window)
    • FIND NPM (opens new window)
    • CODE PEN (opens new window)
    • 印记中文 (opens new window)
    • TOOL.LU (opens new window)
    • 阮一峰-网道 (opens new window)
    • DIGITAL OCEAN (opens new window)
    • DEVDOCS.IO (opens new window)
    • JOI (opens new window)
  • 算法

    • 小浩算法 (opens new window)
    • LABULADONG 的算法小抄 (opens new window)
    • 力扣 SOLUTION (opens new window)
    • HACKER RANK (opens new window)
    • 代码随想录 (opens new window)
  • 博客系列

    • 美团大佬 (opens new window)
    • 蜡笔小伟 (opens new window)
    • 优秀博客1 (opens new window)
    • 优秀博客2-umi (opens new window)
    • 优质博客 (opens new window)
  • CSS

    • CSS-EASING 库 (opens new window)
    • ROUGH.JS (opens new window)
    • CSS 网站收集
    • UNOCSS (opens new window)
  • 前端

    • PROMISE (opens new window)
    • UNDERSCORE.JS (opens new window)
    • study with BGM (opens new window)
    • nginx【B站视频】 (opens new window)
    • 机器学习
    • Js基础
  • 掘金已购课程

    • 前端自动化测试精讲 (opens new window)
    • 深入浅出 Vite (opens new window)
    • 现代 Web 布局 (opens new window)
    • 前端算法与数据结构 (opens new window)
    • 基于 Vite 的 SSG 框架开发实战 (opens new window)
    • SSR 实战:官网开发指南 (opens new window)
    • WebGL 入门与实践 (opens new window)
    • 玩转 CSS 的艺术之美 (opens new window)
    • 前端调试通关秘籍 (opens new window)
    • React 进阶实践指南 (opens new window)
    • TypeScript 全面进阶指南 (opens new window)
    • 前端缓存技术与方案解析 (opens new window)
    • npm scripts 前端工作流 (opens new window)
    • Webpack5 核心原理与应用实践 (opens new window)
  • 购物车

    • 张鑫旭-技术写作指南 (opens new window)
    • 深入剖析 Node.js 底层原理 (opens new window)
    • 前端开发者的现代 C++ 课 (opens new window)
    • 从前端到全栈 (opens new window)
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

Jacky Wang

行到水穷处,坐看云起时
首页
  • 编码专题
  • 深入浅出 Vite
  • 深入浅出 babel
  • 快速上手API
  • 深入浅出 react
  • Node

    • code-notebook
  • 状态管理

    • redux
  • 前端工程化

    • Wepack
  • React源码

    • React源码
  • 组件库封装

    • 组件库
  • 开发工具

    • Vscode 插件
  • 项目展示
  • 案例中心 (opens new window)
  • First Project
  • 基础算法题
  • 链表题
  • 动态规划
  • 双指针
  • 递归
  • 数据结构
  • 前端学习计划 (opens new window)
  • 技术随笔
  • 转载文章
  • 包管理工具
  • 前端学习周报
  • VSCode插件
  • Promise 专题
  • 函数技巧
  • React 专题
  • 配置文件

    • TSCONFIG-配置 (opens new window)
    • NGINX-配置 (opens new window)
    • 正则规则查询手册 (opens new window)
    • Lint 配置 (opens new window)
  • 教程

    • GIT-教程
    • NPM SCRIPTS-工作流 (opens new window)
    • DOCKER-教程 (opens new window)
    • LERNA-教程 (opens new window)
    • GIT-常用操作整理 (opens new window)
  • VSCode

    • LAUNCH.JSON (opens new window)
  • 指令

    • NPM 指令 (opens new window)
    • NVM 指令 (opens new window)
    • Nginx 指令 (opens new window)
    • YARN 指令 (opens new window)
    • PNPM 指令 (opens new window)
  • 库

    • FS-EXTRA 库 (opens new window)
    • NODE 库-PATH (opens new window)
  • 永远的神

    • 魔法师卡颂-自顶向下学 React 源码 (opens new window)
    • 全栈潇晨 (opens new window)
    • 博客-程序员山月-Daily (opens new window)
    • 淘系前端:冴羽 (opens new window)
  • 系列文章

    • 《图解HTTP》 (opens new window)
    • 《ES6标准入门》 (opens new window)
    • 《现代JavaScript教程》 (opens new window)
    • 《深入浅出Webpack》 (opens new window)
    • VSCode 插件系列:小茗同学 (opens new window)
    • JEST 教程 (opens new window)
    • 前端精读周刊:各种精读系列 (opens new window)
    • 一文吃透系列 (opens new window)
    • 图解 REACT 原理 (opens new window)
  • 实用网站

    • MDN (opens new window)
    • CAN I USE (opens new window)
    • TYPESCRIPT-ESLint-RULES (opens new window)
    • ESLint-RULES (opens new window)
    • FRONT-END TREND (opens new window)
    • NPM TREND (opens new window)
    • 在线分析 Node 依赖 (opens new window)
    • FIND NPM (opens new window)
    • CODE PEN (opens new window)
    • 印记中文 (opens new window)
    • TOOL.LU (opens new window)
    • 阮一峰-网道 (opens new window)
    • DIGITAL OCEAN (opens new window)
    • DEVDOCS.IO (opens new window)
    • JOI (opens new window)
  • 算法

    • 小浩算法 (opens new window)
    • LABULADONG 的算法小抄 (opens new window)
    • 力扣 SOLUTION (opens new window)
    • HACKER RANK (opens new window)
    • 代码随想录 (opens new window)
  • 博客系列

    • 美团大佬 (opens new window)
    • 蜡笔小伟 (opens new window)
    • 优秀博客1 (opens new window)
    • 优秀博客2-umi (opens new window)
    • 优质博客 (opens new window)
  • CSS

    • CSS-EASING 库 (opens new window)
    • ROUGH.JS (opens new window)
    • CSS 网站收集
    • UNOCSS (opens new window)
  • 前端

    • PROMISE (opens new window)
    • UNDERSCORE.JS (opens new window)
    • study with BGM (opens new window)
    • nginx【B站视频】 (opens new window)
    • 机器学习
    • Js基础
  • 掘金已购课程

    • 前端自动化测试精讲 (opens new window)
    • 深入浅出 Vite (opens new window)
    • 现代 Web 布局 (opens new window)
    • 前端算法与数据结构 (opens new window)
    • 基于 Vite 的 SSG 框架开发实战 (opens new window)
    • SSR 实战:官网开发指南 (opens new window)
    • WebGL 入门与实践 (opens new window)
    • 玩转 CSS 的艺术之美 (opens new window)
    • 前端调试通关秘籍 (opens new window)
    • React 进阶实践指南 (opens new window)
    • TypeScript 全面进阶指南 (opens new window)
    • 前端缓存技术与方案解析 (opens new window)
    • npm scripts 前端工作流 (opens new window)
    • Webpack5 核心原理与应用实践 (opens new window)
  • 购物车

    • 张鑫旭-技术写作指南 (opens new window)
    • 深入剖析 Node.js 底层原理 (opens new window)
    • 前端开发者的现代 C++ 课 (opens new window)
    • 从前端到全栈 (opens new window)
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • 编码专题

  • 深入浅出 Vite

  • 快速上手 API

  • 深入浅出Babel

    • 如何封装 @babel:code-frame ?
    • 03.babel-JS解析器梳理
      • 0.前言
      • 1. AST 标准的发展历史
      • 2.纯 ECMAScript parser 解析器—— Esprima 和 acorn
      • 3【ESLint】解析器
        • 3.1 espree ——默认解析器
        • 3.2 @babel/eslint-parser
        • 3.3 @typescript-eslint/parser
      • 4.@babel/parser
      • 3.总结
  • 深入浅出 React

  • 百问掘金
  • 深入浅出Babel
wangjiasheng
2023-10-06
目录

03.babel-JS解析器梳理

# 0.前言

本文主要是梳理 Javascript 语法解析器的发展历史。

希望阅读完本篇内容后,可以清楚以下 parser 的逻辑

AST 解析网址:https://astexplorer.net/ (opens new window)

image-20231006151123442

# 1. AST 标准的发展历史

Mozilla 在 MDN 上公布了火狐浏览器的 JS 引擎 SpiderMonkey(c++ 写的 js 引擎)的 parser api 和 AST 标准,所以当时最早的 JS parser ---- esprima (opens new window) 就是基于 SpiderMonkey 的 AST 标准来实现的,后来形成了 estree 标准 (opens new window)。

SpiderMonkey AST 标准
       ↓
JS parser - esprima   →  estree 标准
1
2
3

当然也不是所有的js parser 都是 estree 标准的,比如 terser、typescript 等都有自己的 AST 标准。

关系如下图所示:

# 2.纯 ECMAScript parser 解析器—— Esprima 和 acorn

  • ESprima :最早的 ECMAScript parser 的语法解析器,在早期支持绝对部分的 ES6 的语法解析。当时很多的前端领域的工具都 基于 esprima 开发的。
  • acorn:
    • 但速度快于 esprima 解析器。
    • 支持插件化开发。

# 3【ESLint】解析器

预览:

espree - 内置解析器
       - 1.0 版本:基于 esprima 封装
       - 2.0 版本:基于 acorn 封装
@babel/eslint-parser - babel 解析器
@typescript-eslint/parser  - ts 解析器
1
2
3
4
5

# 3.1 espree ——默认解析器

这是 eslint 的默认 parser。

  • 2015 年之后,es 标准一年一个版本,而 esprima 的更新速度跟不上,它跟不上也就导致了依赖它的一系列工具都跟不上,所以 eslint 就 fork 了一份 esprima,做了一些扩展。

  • 后期 espree 2.0 基于 acorn 重新实现了,也使用 acorn 的插件机制来扩展语法。

使用方式:通过 env 来设定 ESlint 的默认 ECMAScript parser 的版本。

module.exports = {
  env: {
    // 支持浏览器环境
    browser: true,
    // 识别 CommonJS
    node: true,
    // 识别 ES 的代码,使用 ECMAScript 2021 自动设置 ecmaVersion parser 为 12,
    es2021: true,
  },
};
1
2
3
4
5
6
7
8
9
10

存在的问题:ESLint Github#exprerimental features (opens new window)

image-20231006162854342

# 3.2 @babel/eslint-parser

传统的 espree 只能支持最新版本的 ECMAScript 标准,不支持如下:

  1. stage-3 ECMAScript 标准。
  2. 语法特性,如 jsx\flow\typescipt

此时可以 .eslintrc.js ,切换为 babel 解析器

npm i -D @babel/core @babel/eslint-parser
1

可通过 parseOptions 配置解析器选项。具体内容如下:

  • ecmaVersion: 这个配置和 Acron 的 ecmaVersion (opens new window) 是兼容的,可以配置 ES + 数字(如 ES6)或者ES + 年份(如 ES2015),也可以直接配置为latest,启用最新的 ES 语法。
  • sourceType: 默认为script,如果使用 ES Module 则应设置为module
  • ecmaFeatures: 为一个对象,表示想使用的额外语言特性,如开启 jsx。
overrides: [
  // 处理 JS 文件
  {
    files: ["**/*.{js,jsx}"], // 只处理 js 和 jsx 文件
    parser: "@babel/eslint-parser", // 使用 babel 来解析 js 文件
    parserOptions: {
      sourceType: "module", // 支持 import/export
      allowImportExportEverywhere: false,
      ecmaFeatures: {
        globalReturn: false,
      },
    },
  },
]
1
2
3
4
5
6
7
8
9
10
11
12
13
14

# 3.3 @typescript-eslint/parser

同上,espree 不支持 typescript 语法,传统的做法,切换回 typescript 进行语法支持。

overrides: [
  // 处理 TS 文件
  {
    files: ["**/*.{ts,tsx}"], // 只处理 ts 和 js 文件
    parser: "@typescript-eslint/parser", // 能看懂 TypeScript
    parserOptions: {
      project: ["./tsconfig.json"], 
    },
    extends: [
      // typescript-eslint 的推荐规则,只是这些最佳规则都是针对 TS 的
      "plugin:@typescript-eslint/recommended",
      // tsconfig.json 里 Type Checking 的推荐规则
      "plugin:@typescript-eslint/recommended-requiring-type-checking",
    ],
    plugins: [
      // 使用 typescript x eslint 的插件
      "@typescript-eslint",
    ],
  }
]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

# 4.@babel/parser

Babel 中有两个包可以用于解析 JavaScript 代码,一个是 @babel/parser,另一个是 babel-parser(之前的名字是 babylon)。

  • 在 babel 4 版本前,babylon 基于 acorn 进行开发,但后续已经看不到 acorn 依赖,是直接通过 fork 的 acorn 进行修改。

  • 在 babel 7 版本以前,babel 使用了 Babylon 作为默认的 Javascipt 解析器。但随着 balylon的停止维护,babel 从 7 版本开始推出了一个新的解析器 @babel/parser 。

    其中 acorn 和 babylon 都是由同一位开发人员创建,并且 babylon 在某些情况下具有更好的性能和处理能力。

  • 在babel 7 版本后,@babel/parser 是 Babel 官方推荐的解析器,它是基于 Acorn 解析器的一个 fork 版本,支持最新的 ECMAScript 标准,也支持 JSX 和 TypeScript。

发展脉络如下:

babel 4     ← acorn 解析器
babel 4-7   ← balyon 解析器(fork acorn 源码)
babel 7     ← @babel/parser
1
2
3

其中,@babel/parser 基于 acorn 插件对 estree AST 做了如下扩展:

  • 把 Literal 替换成了 StringLiteral、NumericLiteral、 BigIntLiteral、 BooleanLiteral、 NullLiteral、 RegExpLiteral
  • 把 Property 替换成了 ObjectProperty 和 ObjectMethod
  • 把 MethodDefinition 替换成了ClassMethod
  • Program 和 BlockStatement 支持了 directives 属性,也就是 'use strict'等指令的解析,对应的 ast 是 Directive 和 DirectiveLiteral
  • ChainExpression 替换为了 ObjectMemberExpression 和 OptionalCallExpression
  • ImportExpression 替换为了 CallExpression 并且 callee 属性设置为 Import

文档地址:https://babeljs.io/docs/babel-parser#output (opens new window)

# 3.总结

这一节我们了解了 ECMAScript parser 的历史,基于火狐浏览器的 JS 引擎 SpiderMonkey 的 AST 标准,制定了 espree 的标准,最早的 estree 标准的实现是 esprima。

但是随着 es2015 开始一年一个版本,esprima 的迭代速度逐渐跟不上了,这时候 acorn 流行起来,因为速度更快,而且支持插件扩展。

于是 espree、babel parser(babylon) 等都基于 acorn 来实现各自的 parser。虽然 estree 系列的 js parser 挺多的,但也不是全部,terser、typescript 等都是用自己的 AST。

编辑 (opens new window)
上次更新: 2023/10/10, 0:10:00
如何封装 @babel:code-frame ?
React源码-常量定义

← 如何封装 @babel:code-frame ? React源码-常量定义→

最近更新
01
如何理解浏览器的 user agent 用户代理的含义?
11-05
02
浏览器事件循环机制
10-31
03
浏览器页面渲染机制【2023】
10-15
更多文章>
Theme by Vdoing | Copyright © 2020-2023
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式