babel 学习笔记

参考了很多文章,只是为了搞清楚babel 7 之后容易搞混的概念。

介绍

本文主要解决如下几个问题:

  1. babel 是什么?
  2. babel 的原理是什么?
  3. babel 7 常见的核心包有哪些?
  4. babel 7 的最佳配置实践

一、babel 是什么?

babel 是一个 JavaScript 编译器。

除了常用的 将新语法转换为向后兼容的语法外,还支持如下功能:

  • 支持语法扩展(例如 JSX)
  • 支持静态类型检查的流式语法

二、babel 的原理是什么?

babel 的 三个主要处理步骤分别是:解析(parse)转换(transform)生成(generate)

babel 处理步骤

2.1 解析

解析步骤接收代码并输出抽象语法树(AST)。

  • 词法分析
    词法分析阶段把字符串形式的代码转换为令牌(tokens)流。
  • 语法分析
    语法分析阶段使用令牌中的信息把令牌流转换成 AST 的形式。

2.2 转换

转换步骤接收 AST 并对其进行遍历,在此过程中对节点进行添加、更新及移除等操作。

2.3 生成

代码生成步骤把最终的 AST 转换成字符串形式的代码,同时还会创建源码映射。

三、babel 7 常见的核心包有哪些?

babel 7

3.1 @babel/preset-env

@babel/preset-env 是一个智能的 babel 预设,让你能使用最新的 JavaScript 语法,他会帮你转换成代码的目标运行环境支持的语法,提升你的开发效率并让打包后的代码体积更小。

运行机制:
@babel/preset-env 依赖了许多优秀的开源库,并利用它们维护和增强 Babel 语法转换、语法实现,来支持对于的目标环境的版本的语法、特征。

重要的配置项:

target 可以指定浏览器类型。
这里推荐使用单独的文件 browserslistrc 来指定目标浏览器,因为除了 babel 还有其他插件,例如 postcss 也会用到。

useBuiltIns 配置@babel/preset-env 如何处理 polyfill

  • entry
    这个属性将会把 import "@babel/polyfill 或者 require("@babel/polyfill") 替换成对应环境(基于配置的目标环境)的 polyfill。
  • usage
    按需加载需要的polyfill, 一个打包的 bundle 之后加载一次。
  • false
    不加载polyfill

3.2 @babel/polyfill

@babel/polyfill模块包括core-js 和一个自定义的 regenerator runtime 模块用于模拟完整的 ES2015+ 环境。

  • 新的内置组件:Promise、WeakMap
  • 静态方法:Array.from、Object,assign()
  • 实例方法:Array.prototype.includes
  • 生成器函数

弊端:会污染全局

Babel 7.4 之后废弃了 @babel/polyfill, 不再推荐使用。需要分别引入

import "core-js/stable";
import "regenerator-runtime/runtime";

3.3 @babel/plugin-transform-runtime

@babel/plugin-transform-runtime 是一个可重新使用Babel注入的帮助程序代码以节省代码大小的插件。

诸如“ foobar” .includes(“ foo”)之类的实例方法仅适用于core-js @ 3。
如果您需要填充它们,则可以直接导入“ core-js”或使用@babel/preset-env的useBuiltIns选项。

为什么需要 @babel/plugin-transform-runtime?

默认情况下,辅助函数将被添加到需要它的每个文件中。有时不需要重复,特别是当您的应用程序分布在多个文件中时。

  1. 所有辅助函数都将引用模块@babel/runtime,以避免在编译后的输出中出现重复。运行时将被编译到您的构建中。

  2. 该插件的另一个目的是为您的代码创建一个沙盒环境。如果直接导入core-js或@babel/polyfill及其提供的内置程序(例如Promise,Set和Map),则这些将污染全局范围。虽然这对于应用程序或命令行工具可能是可以的,但是如果您的代码是要发布供他人使用的库,或者您无法完全控制代码运行的环境,则将成为一个问题。

corejs option Install command
false npm install --save @babel/runtime
2 npm install --save @babel/runtime-corejs2
3 npm install --save @babel/runtime-corejs3

四、区分开发依赖和生产依赖

Babel 7.4 版本

需要作为开发依赖的:
@babel/preset-env@babel/plugin-transform-runtime@babel/polyfill

需要作为生产依赖的:
@babel/runtimeregenerator-runtimecore-js

总结

@babel/preset-env 是为了解决按需加载 polyfill
@babel/polyfill 是为了提供语法之外的垫片(内置组件、静态方法、实例方法等)
@babel/plugin-transform-runtime 是为了解决全局污染和辅助函数的重复引入

五、实践

5.1 babel 的疑惑解答

说明一:@babel/preset-env 默认配置,并不能完整的转换 es6、以及 es7、es8 等新提案,它只能够转换新语法,但是对于Array.includes() 、Promise 等并不支持

说明二:@babel/polyfill 提供了语法之外的垫片(内置组件、静态方法、实例方法等),@babel/polyfill 依赖于 core-jsregenerator-runtime 实现的垫片

说明三: babel 7.4 之后废弃了 @babel/polyfill

说明四:core-js 是 JavaScript 的模块化标准库,提供了大部分 ES2015+ 的 polyfill 。现在推荐使用 core-js@3

说明五:regenerator-runtime facebook 出品的一个提供编译 generatorasync/await 的独立运行时。

总结:babel 7.4 之后@babel/preset-env 需要和 core-jsregenerator-runtime 搭配使用,才能提供完整的 ES2015+ 环境

5.2 普通应用的 babel 配置

安装babel 相关的依赖

yarn add @babel/core @babel/preset-env babel-loader --dev
yarn add core-js@3
yarn add regenerator-runtime

webpack.config.js

module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: {
          loader: "babel-loader"
        }
      }
    ]
  }

.babelrc 文件

{
  "presets": [
    [
      "@babel/preset-env", 
      {
        "useBuiltIns": "usage",
        "corejs": 3
      }
    ]
   ]
 }

说明一:babel-loader 是 webpack 的插件, 会默认读取 .babelrc中的配置
说明二:core-js@3regenerator-runtime 需要作为 dependencies, 因为这两个依赖中的部分或全部代码会被引入进代码,作为 polyfill,属于生产依赖。
说明三:useBuiltIns 的参数选择,推荐选择 usage,此选项将按需导入 polyfill。而 entry 会把全部的 polyfill 都引入到打包后的文件中。
说明四:useBuiltIns 会把 polyfill 引入到全局,所以会污染全局。
说明五: useBuiltIns: usage 配置时,需要在主文件中主动引入 core-js

import "core-js/stable";
import "regenerator-runtime/runtime";

5.3 第三方库的 babel 配置(待更新)

@babel/transform-runtime 会从 core-js-pure 这个包里去加载对应的polyfill代码,core-js-pure里面的代码不会污染全局变量,适合第三方库的开发。

-- 2020/01/07 更新 --

参考

babel 中文文档-使用说明
Babel 手册
刘小夕:不容错过的 Babel7 知识
知乎:babel 只编译语法
知乎:致我们学前端的小时光—corejs与env、runtime的不解之缘
知乎:Babel学习系列4-polyfill和runtime差别(必看)
怎么给新手科普Babel:polyfill/preset-env/plugin-transform-runtime
关于Babel你只需要知道三个插件
一口(很长的)气了解 babel
荒山:深入浅出 Babel 上篇:架构和原理 + 实战
倪晓磊:【工程化】@babel/preset-env 与@babel/plugin-transform-runtime 使用及场景区别

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,233评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,013评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,030评论 0 241
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,827评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,221评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,542评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,814评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,513评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,225评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,497评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,998评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,342评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,986评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,055评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,812评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,560评论 2 271
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,461评论 2 266

推荐阅读更多精彩内容