关于javascript:Babel7-相关

41次阅读

共计 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。当这个配置选项为:usageentry@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-jsregenerator-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: usageuseBuiltIns: 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,例如 PromiseSetMap 等,是间接在全局环境下所定义的。因而会影响到所有应用到这些 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:

  1. Automatically requires @babel/runtime/regenerator when you use generators/async functions (toggleable with the regenerator option).
  2. Can use core-js for helpers if necessary instead of assuming it will be polyfilled by the user (toggleable with the corejs option)
  3. 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

  1. 如果应用 @babel/preset-envuseBuiltIns: usage 搭配 browserlist 的这种 polyfill 的形式的话,polyfill 是会净化全局的 (entry 模式也是净化全局 )。不过这种配置的形式会根据指标打包平台来肯定水平上缩小不须要被退出到编译打包流程的 polyfill 的数量,因而这种形式也对应的能较少 bundle 最终的体积大小。
  2. 如果是走 @babel/plugin-transform-runtime 插件的 polyfill 的话不会净化全局。然而这个插件没法利用 browserlist 的指标平台配置的策略。因而在你代码当中只有是应用了 ES6+ 的新 api,一律都会引入对应的 polyfill 文件(而不思考这个新的 api 是否被指标浏览器曾经实现了),这样也会造成 bundle 体积增大。针对这个问题,官网也尝试提供一个新的 babel-polyfills package,以及策略去解决相似的问题。详见对应的文档以及 issue

相干文档

  1. @babel/plugin-transform-runtime
  2. polyfill 还是 transform-runtime

正文完
 0