被低估的 Babel

2024-03-27 00:08
文章标签 babel 低估

本文主要是介绍被低估的 Babel,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

作者 | 袁德鑫
责编 | 陈秋歌

不仅仅是语法解析器,Babel更是一个平台。丰富的插件,让它的扩展变得无限可能。目前饿了么大前端部门正通过插件开发,将Babel应用到无痕埋点、错误日志收集等业务场景中。

概览


Babel 是一个 JavaScript 语法解析器。提到它,相信大家的第一反应是把我们写的 ECMAScript 6 代码转换成浏览器可识别的 ECMAScript 5 代码,而这也正是 Babel 的前身 6to5 名字的由来。随着 Babel 不断的发展,现在它已经不再仅仅为了 6to5 而存在。本文旨在跟大家聊一聊如今的 Babel 是怎样处理我们的代码,以及我们还能用 Babel 做些什么。


谁动了我的代码


Babel 只是语法解析器

实际上说 Babel 是语法解析器并不严谨,因为 babel-core 仅仅是对外暴露了一些 API,而真实的解析器是 Babylon,但本文旨在以功能划分 Babel 的几个重要部分,遂将 Babylon 归入 babel-core。

说到 Babel,有一个不得不提的概念就是抽象语法树(Abstract Syntax Tree 或缩写为 AST),即代码的抽象语法结构的树状表现形式。Babel 就是通过 AST 来理解你的代码,并根据预设的规则来对这棵“树”进行编辑,然后将新的 AST 转换为代码。

图1 Babel 的流程图

那么是 Babel 改动了我的代码吗?不。Babel 自 6.0 起,就不再对代码进行修改。作为一个平台,它本身只负责图1中的 parse 和 generate 流程,修改代码的 transform 过程全都交给插件去做。也就是说,Babel 只是一个语法解析器。很多初次使用 Babel 的开发者会问,“为什么我不配置插件 Babel 就不生效”,正是这个原因。

Plugin——转换的执行者

上面说到 Babel 的 plugin 才是真正改动代码的“元凶”,现在我们就来讲讲 Babel 是怎样改动代码的。

Babel 插件中有一个观察者(visitor)机制,我们可以在 visitor 中预设想要观察的 babel-types,然后对其进行操作。下面以源代码 foo === bar 为例:

module.exports = function ({ types: t }) {return {visitor: {BinaryExpression (path) {        
       const isMatchCondition = path.node.operator !== '===' && // 若操作符不为 === 则不做任何操作t.isIdentifier(path.node.left, { name: 'foo' }) && // 若操作符左侧不为变量或变量名不为 foo 则不做任何操作t.isIdentifier(path.node.right, { name:
'bar' }) // 若操作符右侧不为变量或变量名不为 bar 则不做任何操作if (isMatchCondition) {path.node.left = t.identifier('sebmck') // 把操作符左侧的变量名改为 sebmckpath.node.right = t.identifier('dork') // 把操作符右侧的变量名改为 dork}}}} }

编写如上插件,我们的代码经过编译就会得到 sebmck === dork,一个最基本的 Babel Plugin 就大功告成啦。

Preset——转换规则的集合

相信大家对于 Babel Preset 都不陌生。很多开发者的项目中,Babel 的配置都会有一段 "presets": ["es2015"]。接下来我们就以 babel-preset-es2015 为例,一起来看看 preset 内部究竟是什么样子的。

打开 babel-preset-es2015 的源代码,你会发现整个 preset 其实就是一些插件的集合。如果说 plugin 是处理代码的规则,那么 preset 就是一组规则的集合。你完全可以自己拼装不同的插件,生成一个新的预设。

通过Babel可以做什么


Babel 最基础和广泛的用法就是将 ES6 代码转换为 ES5 代码。除此之外,官方还提供了 JSX 语法支持、Flow 语法支持等插件。接下来我们要聊的是一些由社区开发,基于 Babel 或与 Babel 息息相关的开源插件。

Prepack——代码性能优化

前一阵子由 Facebook 团队推出的 Prepack 在前端圈可谓一石激起千层浪,在各类技术社区中也引发了激烈的讨论。本文暂且不谈现阶段 Prepack 是否适用于业务生产环境,只根据 Prepack 的特性和原理,聊一聊 Prepack 与 Babel 擦出了怎样的火花。

Prepack 是一个 JavaScript 代码优化工具。它能够完成一些可以在编译阶段执行的计算工作,将一部分代码替换为等价但更简单的赋值语句,从而省去大量的计算和对象分配工作。

我们先通过一张 Sebastian McKenzie 在 React-Europe 2016 分享 Prepack 的相关视频截图,来看一下 Prepack 的工作原理,如图2所示。

图2 Prepack的工作原理

从上图可见,Prepack 的 Code => ASTAST => Code 都是通过 Babel 来完成的。当你想要在预编译阶段做一些事情的时候,自己做一个符合 ECMAScript 标准的编译器是不太明智的。Babel 完美地解决了这个问题,它既可以为业务开发者服务,又可以为编译工具开发者服务。

babel-plugin-import——指定库的按需加载

在 Webpack 2 推出 Tree Shaking 之前,按需引入一直是前端工程中令人头疼的问题,即使你写的是:

import { module } from 'library'

编译后的结果也会是:

var module = require('library').module

也就是说,模块并没有按需引入,依然加载了所有的代码。为此,ant-design 团队做了一个叫做 babel-plugin-import 的 Babel 插件,通过简单的配置就可以把如下代码:

import { Button } from 'antd'

编译成:

var _button = require('antd/lib/button')

这样就避免了只想用其中一个很小的模块,却要引入整个类库的尴尬。

具体的实现大家可以看它的源代码(https://github.com/ant-design/babel-plugin-import/blob/master/src/Plugin.js)。

babel-eslint——代码风格检查

相信大家对 ESLint 不会很陌生。ESLint 也是通过 AST 对代码进行解析,但 ESLint 团队使用的是自己开发的 Espree。这就导致当 Babel 支持了一种新的自定义语法(如 Flow)时,ESLint 无法直接支持,因此 babel-eslint 就出现了。

ESLint 团队在 Why another parser 中写道:

ESLint had been relying on Esprima as its parser from the beginning. While that was fine when the JavaScript language was evolving slowly, the pace of development increased dramatically and Esprima had fallen behind. ESLint, like many other tools reliant on Esprima, has been stuck in using new JavaScript language features until Esprima updates, and that caused our users frustration.

ESLint 团队曾经为了跟随 JavaScript 的快速发展而选择自行开发语法解析器,现在却又被其拖累,不得不再推出一个使用 Babel 作为解析器的版本。

定义一套语法

经常听到有开发者报怨 JavaScript 语言设计得太烂了,要是能用 XXX 语言来写前端就好了。那么现在机会来了,虽然 Babel 不能识别不符合 ECMAScript 标准的语法,但是它允许你自定义规则。也就是说,你完全可以自己定义一套语法,愉快地用 XXX 语言来做前端开发!

在饿了么大前端的一些实践

Babel 的平台化和插件化使它变得极易扩展。这种灵活性使得我们可以对它寄予无限的期望:不管你是想对代码进行转换,还是仅仅想引入一个语法解析器,Babel 都可以胜任。 除了社区提供的工具,目前饿了么大前端部门在尝试通过 Babel 插件实现一些对业务的扩展,比如:

  • 无痕埋点:目前主流的前端埋点方式还是手工打点。这样做的效率不高,而且每次添加新的埋点还需要发版和等待数据收集。我们正在尝试通过 Babel 插件注入打点代码,并在筛选数据时通过给函数名做标记的方式,随时获取过去一段时间内的埋点信息。

  • 错误日志收集:目前市面上的前端错误日志收集主要还是依赖于捕获错误的堆栈信息。生产环境上的代码都经过了混淆,这给识别工作带来了很大的麻烦。我们正在尝试在 catch 语句中直接注入源代码的信息,尽可能收集更加准确和详细的错误信息。

总结


说了这么多,就是希望大家改变对 Babel 的看法,不再仅仅把它当成一个 6to5 的工具来用。如果你想在预编译阶段做些什么,Babel 是你最好的选择。

近几年,前端在预编译阶段的应用取得了很不错的成绩,我相信在未来的一段时间,会有越来越多与 Babel 相关的好工具出现。

作者简介:袁德鑫,就职于饿了么大前端,目前在探索前端预编译阶段的无痕埋点。

本文为《程序员》原创文章,未经允许不得转载,更多精彩文章请点击「阅读原文」订阅《程序员》

SDCC 2017


11月25日, SDCC 2017“前端技术实战线上峰会”将在CSDN学院以线上直播形式召开。


作为SDCC系列技术峰会的一部分,来自阿里巴巴、苏宁云商、美团点评、饿了么、去哪儿网、白鹭时代等多家企业的前端专家及技术图书作者,将围绕React、AngularJS、Weex前端热门框架在企业中的应用实践,及WebAssembly、MVVM等技术热点展开深入分享,帮助大家解决实际生产中遇到问题。每个演讲时段均设有答疑交流环节,与会者和讲师可零距离互动。


扫描下方二维码,欢迎入群交流。


这篇关于被低估的 Babel的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/850318

相关文章

【ReactJS】困惑于text/babel与browser.js还是babel.js?

使用JSX   使用JSX,可以极大的简化React元素的创建,JSX抽象化了React.createElement()函数的使用,其语法风格类似于HTML语法风格。对比如下代码可以让你更好的理解这一点。 // 使用React.createElement()return React.createElement('div',null,'Hello',this.props.name);//使用J

React第四章(babel)

Babel 什么是Babel? Babel 是一个 JavaScript 编译器,提供了JavaScript的编译过程,能够将源代码转换为目标代码。 AST -> Transform -> Generate 官网 https://babeljs.io/ 查看AST https://astexplorer.net/ Babel所有的包 https://babeljs.io/docs/

神奇的babel

2015年,ECMA推出es6,在es5的基础上添加了各种人性化开发的新特性,详见es2015 让人头疼的是当下主流浏览器的JS引擎并不识别es6语法,所以我们需要将es6的语法翻译成es5的形式再提交给js引擎执行。 那有没有好的工具来实现两种标准之间的转换呢,有,babel。 好,既然用到babel,那么第一步肯定要在项目中安装babel。安装的方法可参照点击打开链接 npm i

被低估的SQL

SQL是现代数据库管理系统中不可或缺的一部分。尽管它的使用已十分普遍,但在数据处理领域,SQL的某些功能和潜力仍然被许多人低估。接下来,小编将与您一起,探讨SQL的一些被忽视的特性,揭示它在数据管理中的真正实力。 1. 窗口函数(Window Functions) 窗口函数在SQL中是一个强大的工具,但往往被新手用户忽视。与传统的聚合函数不同,窗口函数可以在不需要分组的情况下,执

babel-preset-stage-2

http://www.cnblogs.com/chris-oil/p/5717544.html

webpack学习之6.Babel 7

介绍 Babel用于将ES6+转换为ES5。 Babel本身不具有任何转换功能,它把转换的功能分解到一个个插件中。如果不配置插件,使用babel命令转换的代码并没有什么变化。 Babel转换ES6或其他规范可能需要十几二十个插件,为了使开发者不需要一个个添加安装配置,Babel提供了几组插件的集合,称为预设(preset)。开发者可以直接使用预设。 例如推荐的预设 env(@babel/p

【例子】webpack配合babel实现 es6 语法转 es5 案例 [通俗易懂]

首先来说一下实现 es6 转 es5 的一个简单步骤 1、新建一个项目,并且在命令行中初始化项目 npm init -y2、安装对应版本的 webpack webpack-cli(命令行工具) "webpack""webpack-cli"3、安装 Babel 核心库和相关的 loader "babel-core""babel-loader""babel-preset-env"4、在项目根目录

深入浅出 Babel:现代 JavaScript 的编译器

在现代前端开发中,JavaScript 的版本更新速度非常快,新的语法和特性层出不穷。然而,旧版本的浏览器并不总是支持这些新特性。为了确保代码的兼容性和稳定性,我们需要一个工具来将现代 JavaScript 代码转换为旧版本的代码。Babel 就是这样一个工具。 什么是 Babel? Babel 是一个 JavaScript 编译器,主要用于将现代 JavaScript 代码(ES6+)转

babel runtim 和babel pollyfill

对于 Babel < 7.4.0 时,类库/工具项目应选择 @babel/runtime,其他项目选择 @babel/polyfill,当 Babel >= 7.4.0 时,一律使用 @babel/runtime。 babel-polyfill Babel 默认只转换新的 JavaScript 语法,而不转换新的 API。例如,Iterator、Generator、Set、Maps、Pr

babel-runtime和babel-polyfill的作用介绍和使用 -- 见路由权限项目用到

Babel编译转码的范围 Babel默认只转换新的JavaScript语法,而不转换新的API。 例如,Iterator、Generator、Set、Maps、Proxy、Reflect、Symbol、Promise 等全局对象,以及一些定义在全局对象上的方法(比如 Object.assign)都不会转译。 如果想使用这些新的对象和方法,则需要为当前环境提供一个polyfill https:/