babel的一些常用知识点整理

9次阅读

共计 3488 个字符,预计需要花费 9 分钟才能阅读完成。

关于 bable 的一些知识点整理
babel-polyfill 的作用 和 runtime
babel-cli babel-core
babel-preset-env babel-preset-preset-stage-2
babel-loader
babel 使用方法:

使用单体文件
使用命令行
构建工具的插件

运行方式和插件
babel 总共分为 3 个阶段: 解析,转换和生成
babel 本身不具有任何转换功能,如果没有 plugin, 那么经过 babel 的代码和输入的是相同的。
babel 插件分为两种

语法插件:在解析的过程中,能使 babel 能够解析更多的语法
转译插件: 在转换的过程中将代码输出。比如将箭头函数转译成正常的函数

用了转译插件后,就不需要用语法插件了,因为同一语法可能同时存在语法插件和转译插件。
常用的一些插件问题
preset
preset 是一套规范,里面包含了几十个转译插件。这是一组插件的集合
preset 可以分为下面几种:

按官方内容: env, react, flow, minify

stage-x, 包含当年最新规范的草案,每年更新每个 stage 是不一样的,可以分为以下几点

Stage 0 – 稻草人: 只是一个想法,经过 TC39 成员提出即可。
Stage 1 – 提案: 初步尝试。
Stage 2 – 初稿: 完成初步规范。
Stage 3 – 候选: 完成规范和浏览器初步实现。
Stage 4 – 完成: 将被添加到下一年度发布。

低一级的 stage 会包含所有高级 stage 的内容,stage- 1 包含 stage-2,stage- 3 的所有内容。

stage-4 在下一年更新会直接放到 env 中,所以没有单独的 stage- 4 可供使用。

env 是一个每年更新的 preset.

执行顺序

plugin 会运行在 Preset 之前
plugin 从前到后顺序执行
preset 的顺序是从后向前

插件和 preset 只要列出字符串格式的名字即可。但如果某个 preset 或者插件需要一些配置项(或者说参数),就需要把自己先变成数组。第一个元素依然是字符串,表示自己的名字;第二个元素是一个对象,即配置对象。
“presets”: [
// 带了配置项,自己变成数组
[
// 第一个元素依然是名字
“env”,
// 第二个元素是对象,列出配置项
{
“module”: false
}
],

// 不带配置项,直接列出名字
“stage-2”
]

babel-cli
cli 是命令工具,安装了之后,就能够在命令行中使用 babel 命令来编译文件
所以 babel-cli 安装为 devDependencies
### babel-node
babel-node 是 babel-cli 的一部分,不需要独立安装
他使得能够在 node 环境中,直接运行 es2015 的代码,不需要额外进行转码。
babel-node = babel-polyfill + babel-register
### babel-register
babel-register 改写 require 命令,为它加上一个钩子。每当使用 require 加载.js、.jsx、.es 和 .es6 后缀名的文件,就会先用 babel 进行转码。
使用时,必须先加载 require(‘babel-register’)。但是 babel-register 只会对加载的文件转码,对当前文件是不会骑左右的。
而且他属于实时转码,只适用于开发环境使用。
### babel-polyfill
babel 只转换 js 语法,不转换 API,如 Iterator、Generator、Set、Maps、Proxy、Reflect、Symbol、Promise 等全局对象,以及一些定义在全局对象上的方法 (比如 Object.assign) 都不会转码。
但是可以用 babel-polyfill 进行转码。
使用时,在所有代码运行之前增加 require(‘babel-polyfill’)。或者更常规的操作是在 webpack.config.js 中将 babel-polyfill 作为第一个 entry。因此必须把 babel-polyfill 作为 dependencies 而不是 devDependencies
但是他的缺点是:

使用 babel-polyfill 会导致打出来的包非常大。babel-polyfill 是一个整体,把所有的方法都加到原型链上。如果我们只使用了 Array.from,但是他会把 Object.defineProperty 也给加上。
babel-polyfill 会污染全局变量,给很多类的原型链上都作了修改。

所以在实际过程中,通常倾向于用 babel-plugin-transform-runtime
但是如果代码中有高版本的 js 中类型的实例方法([1,2,3].includes(1)), 就只能用 polyfill 了。这个相当于是垫片。
babel-runtime 和 babel-plugin-transform-runtime
bable 会转译 js 语法,举个 async/await 例子
// babel 添加一个方法,把 async 转化为 generator
function _asyncToGenerator(fn) {return function () {….}} // 很长很长一段

// 具体使用处
var _ref = _asyncToGenerator(function* (arg1, arg2) {
yield (0, something)(arg1, arg2);
});

这里_asyncToGenerator 在当前文件被定义的,然后被使用了。如果每个文件都有用 async/await 方法,那么每个文件都会有_asyncToGenerator 这段,会导致重复和浪费。
用了 babel-plugin-transform-runtime 之后,转换的代码就变成
// 从直接定义改为引用,这样就不会重复定义了。
var _asyncToGenerator2 = require(‘babel-runtime/helpers/asyncToGenerator’);
var _asyncToGenerator3 = _interopRequireDefault(_asyncToGenerator2);

// 具体使用处是一样的
var _ref = _asyncToGenerator3(function* (arg1, arg2) {
yield (0, something)(arg1, arg2);
});

这里就相当于引用了一个模块代码,就不存在重复的问题了。
所以这就是用 babel-plugin-transform-runtime 的好处,而 babel-runtime 就是为这些方法提供了集合。所以在使用 babel-plugin-transform-runtime 的时候,需要 babel-runtime 做依赖。
babel-runtime
babel-runtime 内部集成了

core-js: 转换一些内置类 (Promise, Symbol) 和静态方法(Array.from 等)。绝大部分的引用都是这里做的,自动引入。
regenerator:是作为 core-js 的拾遗补漏,主要是 generator/yield 和 async/await 两组做支持。当代码中有 generators/async 时会自动引入。
helpers

babel-plugin-transform-runtime 不支持 实例方法 (例如 [1,2,3].includes(1))
babel-loader
主要使用在构建工具中。babel-loader 和 babel-cli 一样,会读取.babelrc 或者 package.json 中的 babel 段作为自己的配置,但是 babel-loader 必须要和 webpack 做交互。

名称
作用
备注

babel-cli
允许命令行使用 babel 命令转译文件

babel-node
允许命令行使用 babel-node 直接转译 + 执行 node 文件
随 babel-cli 一同安装.babel-node = babel-polyfill + babel-register

babel-register
改写 require 命令,为其加载的文件进行转码,不对当前文件转码
只适用于开发环境

babel-polyfill
为所有 API 增加兼容方法
需要在所有代码之前 require,且体积比较大

babel-plugin-transform-runtime & babel-runtime
把帮助类方法从每次使用前定义改为统一 require,精简代码
babel-runtime 需要安装为依赖,而不是开发依赖

babel-loader
使用 webpack 时作为一个 loader 在代码混淆之前进行代码转换

一口 (很长的) 气了解 babel

正文完
 0