原文出处 babel-preset-env: a preset that configures Babel for you
babel-preset-env 一个帮你配置babel的preset,根据配置的目标环境自动采用需要的babel插件。
问题
目前,几个presets就能让你确定babel应该支持那些功能:
babel-preset-es2015
,babel-preset-es2016
等:支持不同版本的ECMAScript规范。es2015
转译了ES6比ES5的新特性,es2016
转译了ES2016比ES6的新特性等等。babel-preset-latest
: 支持现有所有ECMAScript版本的新特性,包括处于stage 4里的特性(已经确定的规范,将被添加到下个年度的)。
问题是这些presets有时做的多余了,举个例子,大部分现代浏览器已经支持ES6的generators了,但是如果你设置了babel-preset-es2015
,generator函数还是会被转译成复杂的ES5代码。
解决方案
babel-preset-env
功能类似 babel-preset-latest
,优点是它会根据目标环境选择不支持的新特性来转译。
note:实验性的属性(babel-preset-latest
不支持的)需要手动安装配置相应的plugins或者presets。这样你再不需要 es20xx
presets了。
浏览器
你可以选择指定相应的浏览器配置:
browsers参数在这里查询 browserslist . 举个例子:
支持每个浏览器最近的两个版本和IE大于等于7的版本所需的polyfill和代码转译。
"babel": { "presets": [ [ "env", { "targets": { "browsers": ["last 2 versions", "ie >= 7"] } } ] ] },
支持市场份额超过5%的浏览器。
"targets": { "browsers": "> 5%"}
指定浏览器版本:
"targets": { "chrome": 56 }
Node.js
如果你通过Babel编译你的Node.js代码,babel-preset-env
很有用,设置 "targets.node"
是 "current"
,支持的是当前运行版本的nodejs:
"babel": { "presets": [ [ "env", { "targets": { "node": "current" } } ] ] },
我的GitHub上有个测试node参数的例子,请参考 async-iter-demo
.
其他配置
下面会列举 babel-preset-env
部分常用配置。所有配置请查看点击 env preset; 中文版本。
modules
(string, 默认值: "commonjs"
)
将ES6模块语法转换为另一种模块类型,可选值:
各种流行的模块化规范:
"amd"
、"commonjs"
、"systemjs"
、"umd"
禁止转译:
false
include
, exclude
(Array of strings, 默认值: []
)
include
必须要转译的功能 (比如 覆盖有故障的本地功能)。跟单独启用相应插件是一样的。exclude
禁止转译的功能。
useBuiltIns
(boolean, 默认值: false
)
babel为标准库中的新功能提供了polyfill,为内置对象,静态方法,实例方法,生成器函数提供支持。 babel-preset-env
可以实现基于特定环境引入需要的polyfill。
两种使用方法:
core-js
, 根据需要引入ES5,ES6+标准方法的实现。安装 polyfill:
npm install core-js --save
引入 polyfill:
import "core-js";
babel-polyfill
包含core-js
和regenerate-runtime (提供 async 语法编译后的运行时环境)。安装 polyfill:
npm install babel-polyfill --save
引入 polyfill:
import "babel-polyfill";
两种方法最终都会根据环境转译成特定的polyfill。 比如:
import "core-js/modules/es7.string.pad-start";import "core-js/modules/es7.string.pad-end";import "core-js/modules/web.timers";import "core-js/modules/web.immediate";import "core-js/modules/web.dom.iterable";
note:
在整个应用里只能引入一次polyfill,可以在 “main” 模块里一次引入。
useBuiltIns
会使浏览器下载的代码变少 (最终打包的文件大小变小了)。但是不会节约内存, 因为polyfill本身只会安装缺少的部分。
更多polyfill的内容请参考《Setting up ES6》中的章节:“Babel: configuring standard library and helpers”
debug
(boolean, default: false
)
以下内容都会用console.log
输出 :
目标环境
启用的transforms
启用的plugins
启用的polyfills
尝试下面的示例,瞧瞧console输出。
举例
下面的例子选自preset的readme文件:
{ "presets": [ [ "env", { "targets": { "safari": 10 }, "modules": false, "useBuiltIns": true, "debug": true }] ] }
模块不会被转译,可以将imports和exports让webpack去处理。
debug
的输出如下:
Using targets: { "safari": 10} Modules transform: false Using plugins: transform-exponentiation-operator {} transform-async-to-generator {} Using polyfills: es7.object.values {} es7.object.entries {} es7.object.get-own-property-descriptors {} web.timers {} web.immediate {} web.dom.iterable {}
env是如何基于目标环境去匹配哪些是需要转译的?
根据以下外部数据来确定目标环境支持的情况,可以定期执行build-data.js 来生成 plugins.json。
ECMAScript标准兼容性列表 compat-table。
plugins包含特性列表
plugin-features.js
。
下一步还能做什么?
有可以访问‘环境’ 的插件
未来计划让插件拥有检查当前环境具有什么可能性的能力,两个好处:
一些plugins (比如对象扩展运算符) 目前通过选项告诉他们是否使用本地功能或polyfills。如果能知道当前 “环境”,就不需要配置了。
基于babel的minifiers可以确定是否可以输出。比如,箭头函数。
简化presets
基于ECMAScript版本的Presets (
es2015
等)很多已经过时了 。Babel团队考虑会在未来的版本中移除他们 (比如, 通过废弃处理)。基于TC39不同阶段的提案的Presets (
stage-0,1,2,3
等) 也是去除的候选,因为在这些statges中的标准是不断变化的。提案可以在2个月内改变。因此,直接引用一些实验性的plugins会是更好的选择。
热门评论
我执行 Webpack --config webpack.conf.js,出现这样的错误,你知道哪里出错了吗