意见反馈
帮助中心
官方微信

了解babel:polyfill、loader、 preset-env及 core之间的关系

发布者:Carl
发布时间:2022年12月06日
阅读量:173

之前在用webpack配置babel解析es6语法时,只是按照文档上的使用说明来配置,并没有去真正了解babel的一系列工具链都是怎么回事,今天做一下回顾:

我们常接触到的有babelbabel-loader@babel/core@babel/preset-env 、@babel/polyfill、以及@babel/plugin-transform-runtime,这些都是做什么的?

1、babel:babel官网对其做了非常明了的定义:

Babel 是一个工具链,主要用于在旧的浏览器或环境中将 ECMAScript 2015+ 代码转换为向后兼容版本的 JavaScript 代码:
转换语法
Polyfill 实现目标环境中缺少的功能 (通过 @babel/polyfill)
源代码转换 (codemods)
更多!

我们可以看到,babel是一个包含语法转换等诸多功能的工具链,通过这个工具链的使用可以使低版本的浏览器兼容最新的javascript语法。

需要注意的是,babel也是一个可以安装的包,并且在 webpack 1.x 配置中使用它来作为 loader 的简写 。如:

{
test: /\.js$/,
loader: 'babel',
}

但是这种方式在webpack 2.x以后不再支持并得到错误提示:

The node API forbabelhas been moved tobabel-core

此时删掉 babel包,安装babel-loader, 并制定loader: 'babel-loader'即可

2、@babel/core:

@babel/core是babel的核心库,所有的核心Api都在这个库里,这些Api供babel-loader调用

3、@babel/preset-env:

这是一个预设的插件集合,包含了一组相关的插件,Bable中是通过各种插件来指导如何进行代码转换。该插件包含所有es6转化为es5的翻译规则

babel官网对此进行的如下说明:

Transformations come in the form of plugins, which are small JavaScript programs that instruct Babel on how to carry out transformations to the code. You can even write your own plugins to apply any transformations you want to your code. To transform ES2015+ syntax into ES5 we can rely on official plugins like@babel/plugin-transform-arrow-functions

大致即es6到es5的语法转换是以插件的形式实现的,可以是自己的插件也可以是官方提供的插件如箭头函数转换插件@babel/plugin-transform-arrow-functions。

由此我们可以看出,我们需要转换哪些新的语法,都可以将相关的插件一一列出,但是这其实非常复杂,因为我们往往需要根据兼容的浏览器的不同版本来确定需要引入哪些插件,为了解决这个问题,babel给我们提供了一个预设插件组,即@babel/preset-env,可以根据选项参数来灵活地决定提供哪些插件。为此,我们往往做如下配置:

在预设配置中以targets指定了es6向后兼容的浏览器的最低版本,根据兼容的浏览器的最低版本对es6最新语法的支持性提供需要的转换插件。这里的options可以单独放在.babelrc文件中,babel会自动去读取这些选项参数。

4、@babel/polyfill:

@babel/preset-env只是提供了语法转换的规则,但是它并不能弥补浏览器缺失的一些新的功能,如一些内置的方法和对象,如Promise,Array.from等,此时就需要polyfill来做js得垫片,弥补低版本浏览器缺失的这些新功能。

我们需要注意的是,polyfill的体积是很大的,如果我们不做特殊说明,它会把你目标浏览器中缺失的所有的es6的新的功能都做垫片处理。但是我们没有用到的那部分功能的转换其实是无意义的,造成打包后的体积无谓的增大,所以通常,我们会在presets的选项里,配置"useBuiltIns": "usage",这样一方面只对使用的新功能做垫片,另一方面,也不需要我们单独引入import '@babel/polyfill'了,它会在使用的地方自动注入。

5、babel-loader:

以上@babel/core、@babel/preset-env 、@babel/polyfill其实都是在做es6的语法转换和弥补缺失的功能,但是当我们在使用webpack打包js时,webpack并不知道应该怎么去调用这些规则去编译js。这时就需要babel-loader了,它作为一个中间桥梁,通过调用babel/core中的api来告诉webpack要如何处理js。

6、@babel/plugin-transform-runtime:

polyfill的垫片是在全局变量上挂载目标浏览器缺失的功能,因此在开发类库,第三方模块或者组件库时,就不能再使用babel-polyfill了,否则可能会造成全局污染,此时应该使用transform-runtime。transform-runtime的转换是非侵入性的,也就是它不会污染你的原有的方法。遇到需要转换的方法它会另起一个名字,否则会直接影响使用库的业务代码,

故开发类库,第三方模块或者组件库时使用transform-runtime,平常的项目使用babel-polyfill即可


转载自:https://zhuanlan.zhihu.com/p/138108118



全部评论

没有评论