# @babel/preset-env

@babel/preset-env是一个灵活的预设,你可以无需管理目标环境需要的语法转换或浏览器polyfill,就可以使用最新的 JavaScript。这将让你的生活更简单,也会让 JavaScript 打包文件更小。

# 安装

# with npm
npm install --save-dev @babel/preset-env
1
2
# with yarn
yarn add @babel/preset-env --dev
1
2

# 它如何工作

@babel/preset-env是基于一些优秀的开源项目,比如browserslistcompat-tableelectron-to-chromium,要是没有它们,也就没有@babel/preset-env

我们利用这些数据源来维护一些映射表:

  • 我们支持的设备环境的哪个版本需要获得哪些 JavaScript 语法或浏览器特性的支持的映射
  • 这些语法和特性到 Babel 转换插件和core-jspolyfill的映射

注意

尤其需要注意的是,@babel/preset-env不支持stage-x的插件。

@babel/preset-env拿到你指定的目标环境,检查这些映射表来编译一系列的插件并传给 Babel。

# Browserslist 集成

针对基于浏览器的或Electron-based的项目,我们推荐使用.browserslistrc文件来指定目标环境。你可能已经有了这个配置文件,因为它会被生态系统里的许多工具用到,比如autoprefixerstylelinteslint-plugin-compat等等。

若是没设置targetsignoreBrowserslistConfig配置项,@babel/preset-env默认会使用browserslist config sources

比如,仅仅包含>0.25%市场份额浏览器的那些polyfill和代码转换:

Options:

{
  "presets": [
    [
      "@babel/preset-env",
      {
        // 原文档是这样的
        // "useBuiltIns": "entry",

        // 实际上应该是这样
        "targets": "> 0.25%, not dead"
      }
    ]
  ]
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14

browserslist:

> 0.25%
not dead
1
2

package.json:

{
    "browserslist": "> 0.25%, not dead"
}
1
2
3

# Options

关于更多设置预设的配置项,可参考preset options文档。

# targets

string | Array<string> | { [string]: string },默认为{}

描述你项目支持的目标环境。

这可以使用browserslist-compatible形式的query

{
  "targets": "> 0.25%, not dead"
}
1
2
3

或者支持的最小环境版本的对象:

{
  "targets": {
    "chrome": "58",
    "ie": "11"
  }
}
1
2
3
4
5
6

这些环境可以是:

  • chrome
  • opera
  • edge
  • firefox
  • safari
  • ie
  • ios
  • android
  • node
  • electron

若是没有指定环境,@babel/preset-env默认将转换所有的 ECMAScript 2015+ 代码。

{
  "presets": ["@babel/preset-env"]
}
1
2
3

注意

我们不推荐使用preset-env时不指定环境,因为这样就无法发挥它指定目标浏览器能力的优势。

# targets.esmodules

boolean

你要支持的目标浏览器可能支持ES 模块。当指定该选项,指定的目标浏览器将被忽略。你可以结合<script type="module"></script>来使用这样方式,这样就会产生更小的脚本文件(https://jakearchibald.com/2017/es-modules-in-browsers/#nomodule-for-backwards-compatibility)。

注意

请注意,当指定esmodules后,将忽略浏览器目标环境。

{
  "presets": [
    [
      "@babel/preset-env",
      {
        "targets": {
          "esmodules": true
        }
      }
    ]
  ]
}
1
2
3
4
5
6
7
8
9
10
11
12

# targets.node

string | "current" | true

若是你想要针对当前node版本编译,你可以指定"node": true"node": "current",这与"node": process.versions.node是一样的。

# targets.safari

string | "tp"

若是你想要针对 Safari 的 technology preview 版本编译,你可以指定"safari": "tp"

# targets.browsers

即将在下个版本移除。

# spec

boolean, 默认为false

Enable more spec compliant, but potentially slower, transformations for any plugins in this preset that support them.

# loose

boolean, 默认为false

开启"loose" transformations,针对预设里允许loose转换的任何插件。

# modules

"amd" | "umd" | "systemjs" | "commonjs" | "cjs" | "auto" | false,默认为"auto"

Enable transformation of ES6 module syntax to another module type.

开启将 ES6 模块语法转换为其他模块语法。设置为false将不转换模块。

cjscommonjs的别名。

# debug

boolean, 默认为false

将使用的插件/目标环境以及plugin data version指定的版本输入到console.log

# include

Array<string|RegExp>, 默认为[]

插件数组,这些插件总是被使用(即使目标环境不需要)。

有效的选项包括:

  • Babel 插件,带前缀或不带前缀都支持,比如@babel/plugin-transform-spreadplugin-transform-spread
  • 内置对象,比如es6.mapes6.set、或es6.object.assign

插件名称可以全部或部分指定(或使用正则表达式)。

可接受的输入有:

  • 全部名称,string"es6.math.sign"
  • 部分名称,string"es6.math.*"(解析为所有以es6.math为前缀的插件)
  • RegExp对象:/^transform-.*$/new RegExp("^transform-modules-.*")

注意,上面的.RegExp的一部分,等同于任何字符,而不是实际的字符.。另外注意在RegExp里使用.*匹配任何字符,类似于glob格式里的*

若是原生实现里有bug,或者只实现了特性的一部分时,这个配置项将尤其有用。

比如,Node 4 支持原生的类但是不支持函数参数的扩展运算符。若是调用super时使用扩展运算符,则需要引入@babel/plugin-transform-classes进行转换。

注意

注意,includeexclude选项仅能作用于包含在预设里的插件。因此,若是使用include包含@babel/plugin-proposal-do-expressions插件或是使用exclude排除@babel/plugin-proposal-function-bind,都会抛错。若是想使用不包含在预设里的插件,可以直接添加在plugins里。

# exclude

Array<string|RegExp>,默认为[]

插件数组,这些插件将不会被使用(即使目标环境需要)。

可能的选项与include相同。

该选项设置了一个转换插件的黑名单,比如不使用@babel/plugin-transform-regenerator,若是你不使用生成器函数generators以及不想包含regeneratorRuntime(当使用useBuiltIns时)或使用另一个插件比如fast-async而不是Babel 的async-to-gen

# useBuiltIns

"usage" | "entry" | false,默认是false

注意

该选项会直接添加对core-js模块的引用。因此core-js将相对于文件自身进行解析,这要求core-js是可访问的。在你的项目,若是没有core-js依赖或是有多个版本,你可能需要指定core-js@2作为顶级依赖。

这选项配置@babel/preset-env如何处理polyfill

# useBuiltIns: 'entry'

注意

整个项目里能且仅能有一次使用require("@babel/polyfill");。多次引入@babel/polyfill将抛错,因为这将导致全局冲突以及其他难以追踪的问题。我们推荐创建一个单独的入口你文件,仅仅包含require语句。

该选项启用一个新的插件,该插件将基于你环境单独引入core-js的各个文件,以此来替换掉import "@babel/polyfill"require("@babel/polyfill")语句。

npm install @babel/polyfill --save
1

输入:

import "@babel/polyfill";
1

输出(基于环境而不同):

import "core-js/modules/es7.string.pad-start";
import "core-js/modules/es7.string.pad-end";
1
2

这对直接引入core-js也是有效的(import "core-js";require('core-js');)。

# useBuiltIns: 'usage'(实验性的)

添加对每个文件中使用的特定的polyfill的引入。我们利用了“一个打包文件将只加载一次相同的polyfill”这一事实。

输入:

// a.js
var a = new Promise();
1
2
// b.js
var b = new Map();
1
2

输出(若是环境不支持):

import "core-js/modules/es6.promise";
var a = new Promise();
1
2
import "core-js/modules/es6.map";
var b = new Map();
1
2

输出(若是环境支持):

var a = new Promise();
1
var b = new Map();
1

# useBuiltIns: false

每个文件里不自动添加polyfill,或不将import "@babel/polyfill"转换为单独的polyfill

# forceAllTransforms

boolean,默认为false

有了 Babel 7 的Javascipt config file支持,若是env被设置为product,你可以强制使用所有的转换。

module.exports = function(api) {
  return {
    presets: [
      [
        "@babel/preset-env",
        {
          targets: {
            chrome: 59,
            edge: 13,
            firefox: 50,
          },
          // for uglifyjs...
          forceAllTransforms: api.env("production"),
        },
      ],
    ],
  };
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

注意

targets.uglify已经废弃并将在下个主版本移除。

默认情况下,这个预设将会按需运行目标环境需要的所有转换。若是你想要运行所有的转换(而忽略目标环境是否需要),则需要开启该选项,这对于输出代码在 UglifyJS 上或仅支持 ES5 的环境上运行来说将是非常有用的。

注意

Uglify 有一个在建的"Harmony"分支来设法解决 ES6 支持缺失的问题,但是这还不太稳定。你可以在UglifyJS2 issue #448关注这个进度。如果你想要一个支持 ES6 语法的可选的压缩工具,我们推荐使用babel-minify

# configPath

string,默认为process.cwd()

搜索 Browserslist 配置的开始点,会基于此开始点向上搜索到系统根目录,直到发现配置文件。

# ignoreBrowserslistConfig

boolean,默认为false

切换是否使用browserslist config sources,这将决定是否要搜索任何的 Browserslist 配置文件或package.json里的browserslist选项。当项目里存在 Browserslist 配置文件但是不用于 Babel 编译时,这将非常有用。

# shippedProposals

切换是否开启对处于提案中的且浏览器已经实现的内置对象/特性的支持。若是你的目标环境已经有了对某提案特性的原生支持,将开启与其相匹配的解析器语法插件,而不是执行任何的转换。注意,这不会开启与@babel/preset-stage-3相同的转换,因为这些提案在正式落地到浏览器之前还会继续改变。

当前以下内容是支持的:

Builtins

Features

  • None

# @vue/babel-preset-env

@vue/babel-preset-env是针对 Vue.js 项目,基于@babel/preset-env@vue/babel-preset-jsx@babel/plugin-transform-runtime等等预设和插件的封装,主要包含了以下内容:

  • @babel/preset-env:主要使用该预设,并基于用户输入和目标环境等对参数进行了处理。
    • polyfills
      • @vue/babel-preset-env里默认包含了以下polyfill,详见源码,但是这些polyfill会根据目标环境来确定最终是否会传入@babel/preset-env预设里。假设目标环境都实现了这些内置对象或特性,则最终不会包含这些polyfill。详见源码
        • es6.array.iterator
        • es6.promise
        • es6.object.assign
        • es7.promise.finally
  • @babel/plugin-transform-runtime:仅使用了该插件引入模块化的helpers替换内联的 Babelhelpers
  • @babel/plugin-syntax-dynamic-import
  • @babel/plugin-proposal-decorators
  • @babel/plugin-proposal-class-properties
  • 等等
本站总访问量    次