mrbone / mrbone.github.io

0 stars 0 forks source link

babel-preset-env #82

Closed mrbone closed 6 years ago

mrbone commented 6 years ago

babel-preset-env 简介

默认情况下,babel-preset-env 和 babel-preset-latest(已弃用) 一样,包含三个 preset(babel-preset-es2015, babel-preset-es2016, and babel-preset-es2017)。

我们用一个简单的 Map 测试。

//source
var map = new Map();

var keyString = 'a string';

map.set(keyString, 'string\'s value');

console.log(map.get(keyString));

console.log(map.get('a string'));

默认情况下输入的结果除了加了一行 use strict 以外就啥也没做了。

//output
'use strict';

var map = new Map();

var keyString = 'a string';

map.set(keyString, 'string\'s value');

console.log(map.get(keyString));

console.log(map.get('a string'));

这个时候我们增加编译环境 target,babel-preset-env 使用的是 browserlist 语法 做浏览器切分。这个配置可以放到 .babelrc

{
  "presets": [
    ["env", {
      "targets": {
        "browsers": ["IE 8"]
      }
    }]
  ]
}

这个时候我们把 debug 选项打开则可以看到 babel-preset-env 使用了具体哪些 plugin。

babel-preset-env: `DEBUG` option

Using targets:
{
  "ie": "8"
}

Modules transform: commonjs

Using plugins:
  check-es2015-constants {"ie":"8"}
  transform-es2015-arrow-functions {"ie":"8"}
  transform-es2015-block-scoped-functions 
  ...
  syntax-trailing-function-commas {"ie":"8"}

现在 env 帮我们把语法层面的 transform-plugin 都搞进来了,但是我们发现在上面的输出代码中并没有 polyfill 进 Map 类,我们可以手动引入 core-js 对应的包,也可以全部交给 babel-preset-env,只需要改下配置

{
  "presets": [
    ["env", {
      "targets": {
        "browsers": ["IE 8"]
      },
      "debug": true,
+      "useBuiltIns": true
    }]
  ]
}

这个时候我们再 build 以后看下输出

Using targets:
{
  "ie": "8"
}

Modules transform: commonjs

Using plugins:
  check-es2015-constants {"ie":"8"}
  transform-es2015-arrow-functions {"ie":"8"}
  transform-es2015-block-scoped-functions {"ie":"8"}
  transform-es2015-block-scoping {"ie":"8"}
  transform-es2015-classes {"ie":"8"}
  transform-es2015-computed-properties {"ie":"8"}
  transform-es2015-destructuring {"ie":"8"}
  transform-es2015-duplicate-keys {"ie":"8"}
  transform-es2015-for-of {"ie":"8"}
  transform-es2015-function-name {"ie":"8"}
  transform-es2015-literals {"ie":"8"}
  transform-es2015-object-super {"ie":"8"}
  transform-es2015-parameters {"ie":"8"}
  transform-es2015-shorthand-properties {"ie":"8"}
  transform-es2015-spread {"ie":"8"}
  transform-es2015-sticky-regex {"ie":"8"}
  transform-es2015-template-literals {"ie":"8"}
  transform-es2015-typeof-symbol {"ie":"8"}
  transform-es2015-unicode-regex {"ie":"8"}
  transform-regenerator {"ie":"8"}
  transform-exponentiation-operator {"ie":"8"}
  transform-async-to-generator {"ie":"8"}
  syntax-trailing-function-commas {"ie":"8"}

Using polyfills:
  es6.typed.array-buffer {"ie":"8"}
  es6.typed.data-view {"ie":"8"}
  es6.typed.int8-array {"ie":"8"}
  es6.typed.uint8-array {"ie":"8"}
  es6.typed.uint8-clamped-array {"ie":"8"}
  ...

我们可以看到除了 plugin 以外,对应的 polyfill的包也出现在 debug 信息中,但这个时候还没有结束,我们需要手动引入 babel-polyfill

+import 'babel-polyfill';
...

然后我们再看下 build 之后的文件。

'use strict';

require('core-js/modules/es6.typed.array-buffer');

require('core-js/modules/es6.typed.data-view');

require('core-js/modules/es6.typed.int8-array');
...

var map = new Map();

var keyString = 'a string';

map.set(keyString, 'string\'s value');

console.log(map.get(keyString));

console.log(map.get('a string'));

总结

babel-preset-env 并不是根据使用到的语法来判断需要准备的 plugin 和对应的 polyfill,而是在 compile 阶段之前就根据 target 生成 plugin 和 polyfill 列表,然后根据这个列表做转换,所以说像这个示例中,我们就算只使用了一个 Map 类,也会把 es6 的所有 polyfill 包搞进来,所以是否使用 useBuiltIns:true 还要根据项目的情况来看。