共计 4868 个字符,预计需要花费 13 分钟才能阅读完成。
文章首发于集体 github blog: Biu-blog,欢送大家关注~
@babel/preset-env
@babel/preset-env
次要的性能是根据我的项目通过 babel
编译构建后产生的代码所对应运行的指标平台。@babel/preset-env
外部依赖了很多插件:@babel/plugin-transform-*
。这些插件的工作次要就是 babel
在解决代码的过程当中对于新的 ES 语法的转换,将高版本的语法转化为低版本的写法。例如 @babel/plugin-transform-arrow-function
是用来转化箭头函数语法的。
根本的配置办法:
// babel.config.json
{
"presets": [
[
"@babel/preset-env",
{// 相干 preset 的配置}
]
]
}
对于 web
侧的我的项目或者 基于 Electron
的我的项目,个别会搭配着 .browserlistrc
(或 package.json
里的 browserslist
字段 ) 来应用(确定最终构建平台)。
相干 options 配置
useBuiltIns
“usage” | “entry” | false, defaults to false.
这个配置选项也决定了 @babel/preset-env
如何去援用 polyfills。当这个配置选项为:usage
或 entry
,@babel/preset-env
会间接建设起对于 core-js
相干 module 的援用。因而这也意味着 core-js
会被解析为对应的相对路径同时须要确保 core-js
在你的我的项目当中曾经被装置了。
因为从 @babel/polyfill
从 7.4.0 版本开始就被弃用了, 因而举荐间接配置 corejs
选项,并在我的项目当中间接装置 core-js
。
useBuiltIns: ‘entry’
应用这种形式的配置须要在你的业务代码当中注入:
import 'core-js/stable'
import 'regenerator-runtime/runtime'
在 babel
解决代码的过程当中,会引入一个新的插件,同时 @babel/preset-env
会依据指标平台,例如 target
当中的配置,或者是 .browserlistrc
等来引入对应平台所须要的 polyfill
:
In:
import 'core-js'
Out(different based on environment):
import "core-js/modules/es.string.pad-start"
import "core-js/modules/es.string.pad-end"
注:其实这里的 useBuiltIns: entry
的配置以及须要在业务代码当中须要注入 core-js
和 regenerator-runtime/runtime
,在业务代码当中注入对应的 package 从应用上来讲更多的是起到了占位的作用,由 @babel/preset-env
再去依据不同的指标平台去引入对应所须要的 polyfill
文件
同时在应用的过程中,如果是 import 'core-js'
那么在解决的过程当中会引入所有的 ECMAScript
个性的 polyfill,如果你只心愿引入局部的个性,那么能够:
In:
import 'core-js/es/array'
import 'core-js/proposals/math-extensions'
Out:
import "core-js/modules/es.array.unscopables.flat";
import "core-js/modules/es.array.unscopables.flat-map";
import "core-js/modules/esnext.math.clamp";
import "core-js/modules/esnext.math.deg-per-rad";
import "core-js/modules/esnext.math.degrees";
import "core-js/modules/esnext.math.fscale";
import "core-js/modules/esnext.math.rad-per-deg";
import "core-js/modules/esnext.math.radians";
import "core-js/modules/esnext.math.scale";
useBuiltIns: ‘usage’
主动探测代码当中应用的新的个性,并联合指标平台来决定引入对应新个性的 polyfill
,因而这个配置是会最大限度的去缩小引入的 polyfill
的数量来保障最终生成的 bundler
体积大小。
不过须要留神的是:因为 babel
解决代码原本就是一个十分耗时的过程,因而在咱们理论的我的项目当中个别是对于 node_modules
当中的 package
进行 exclude
配置给疏忽掉的,除非是一些明确须要走我的项目当中的 babel
编译的 package
会独自的去 include
,所以 useBuiltIns: 'usage'
这种用法的话有个危险点就是 node_modules
当中的第三方包在理论的编译打包解决流程当中没有被解决(例如有些 package
提供了 esm 标准的源码,同时 package.json
当中也配置了 module
字段,那么例如应用 webpack
这样的打包工具的话会引入 module
字段对应的入口文件)
同时,如果应用 useBuiltIns: 'usage'
配置的话。是会在每个文件当中去引入相干的 polyfill
的,所以这里如果不借助 webpack
这种打包工具的话,是会造成代码冗余的。
useBuiltIns: false
Don’t add polyfills automatically per file, and don’t transform import “core-js” or import “@babel/polyfill” to individual polyfills.
corejs
corejs
的配置选项须要搭配着 useBuiltIns: usage
或 useBuiltIns: entry
来应用。默认状况下,被注入的 polyfill 都是稳固的曾经被纳入 ECMAScript
标准当中的个性。如果你须要应用一些 proposals 当中的 feature 的话,那么须要配置:
{
"presets": [
[
"@babel/preset-env",
{
// 相干 preset 的配置
corejs: {
version: 3,
proposals: true
}
}
]
]
}
@babel/plugin-transform-runtime
呈现的背景:
Babel
在编译解决代码的过程当中会应用一些 helper 辅助函数,例如 _extend
。这些辅助函数个别都会被增加到每个须要的被解决的文件当中。
因而 @babel/plugin-transform-runtime
所要解决的问题就是将所有对于须要这些 helper 辅助函数的引入全副指向 @babel/runtime/helpers
这个 module 当中的辅助函数,而不是给每个文件都增加对应 helper 辅助函数的内容。
另外一个目标就是去创立一个沙盒环境。因为如果你间接引入 core-js
,或者 @babel/polyfill
的话,它所提供的 polyfill,例如 Promise
,Set
,Map
等,是间接在全局环境下所定义的。因而会影响到所有应用到这些 API 的文件内容。所以如果你是写一个 library 的话,最好应用 @babel/plugin-transform-runtime 来实现相干 polyfill 的引入,这样能防止净化全局环境。
这个插件所做的工作其实也是援用 core-js
相干的模块来实现 polyfill
的性能。最终所达到的成果和应用 @babel/polyfill
是一样的。
配置办法:
{
"plugins": [
[
"@babel/plugin-transform-runtime",
{"corejs": 3}
]
]
}
The plugin defaults to assuming that all polyfillable APIs will be provided by the user. Otherwise the corejs option needs to be specified.
须要留神的是不同 corejs
版本提供的 helpers 有一些性能上的差别:corejs: 2
仅反对全局的定义,例如 Promise
,和一些静态方法,例如 Array.from
,实例上的办法是是不反对的,例如 [].includes
。不过 corejs: 3
是反对实例上的办法的。
默认状况下,@babel/plugin-transform-runtime
是不会引入对于 proposals 的 polyfill 的,如果你是应用 corejs: 3
的话,能够通过配置 proposal: true
来开启这个性能。
corejs option | Install command |
---|---|
false | npm install --save @babel/runtime |
2 | npm install --save @babel/runtime-corejs2 |
3 | npm install --save @babel/runtime-corejs3 |
技术实现细节
The transform-runtime transformer plugin does three things:
- Automatically requires @babel/runtime/regenerator when you use generators/async functions (toggleable with the regenerator option).
- Can use core-js for helpers if necessary instead of assuming it will be polyfilled by the user (toggleable with the corejs option)
- Automatically removes the inline Babel helpers and uses the module @babel/runtime/helpers instead (toggleable with the helpers option).
What does this actually mean though? Basically, you can use built-ins such as Promise, Set, Symbol, etc., as well use all the Babel features that require a polyfill seamlessly, without global pollution, making it extremely suitable for libraries.
Some tips
- 如果应用
@babel/preset-env
走useBuiltIns: usage
搭配browserlist
的这种polyfill
的形式的话,polyfill
是会净化全局的 (entry
模式也是净化全局 )。不过这种配置的形式会根据指标打包平台来肯定水平上缩小不须要被退出到编译打包流程的polyfill
的数量,因而这种形式也对应的能较少 bundle 最终的体积大小。 - 如果是走
@babel/plugin-transform-runtime
插件的polyfill
的话不会净化全局。然而这个插件没法利用browserlist
的指标平台配置的策略。因而在你代码当中只有是应用了ES6+
的新 api,一律都会引入对应的polyfill
文件(而不思考这个新的 api 是否被指标浏览器曾经实现了),这样也会造成 bundle 体积增大。针对这个问题,官网也尝试提供一个新的babel-polyfills
package,以及策略去解决相似的问题。详见对应的文档以及 issue
相干文档
- @babel/plugin-transform-runtime
- polyfill 还是 transform-runtime