探索下babel-preset-env和babel-plugin-transform-runtime的使用

作者 : 开心源码 本文共5741个字,预计阅读时间需要15分钟 发布时间: 2022-05-13 共209人阅读

本文主要讲 @babel/preset-envuseBuiltIns@babel/plugin-transform-runtime 的使用。

不会讲其他内容。

@babel/preset-env

@babel/preset-env 是一个非常强大的预设,可以帮助我们对JavaScript代码进行语法转换和设置polyfills(假如目标环境需要的话)。

useBuiltIns

这个配置项告诉 @babel/preset-env如何解决 polyfills。它有三个值,分别是 “usage” | “entry” | false, 默认是 false。

useBuiltIns的值为:”usage”|”entry”时,需要指定corejs(自从babel 7.4.0后,@babel/polyfill 被认为过时了)。

corejs 有个两个选择, core-js@3core-js@2。两者的区别是:core-js@2仅支持全局变量(如:Promise)和静态属性(如:Array.from), core-js@3还支持实例属性(如:[].includes)

1.当值为entry

需要在一个入口js文件顶部,手动增加如下代码:

// entry.jsimport "core-js";

而后使用babel编译下,输出结果可能如下:

"use strict";require("core-js/modules/es.symbol");require("core-js/modules/es.symbol.description");require("core-js/modules/es.symbol.async-iterator");// 此处省略n个省略号

babel会根据 @babel/env 的target配置,将目标环境不支持的polyfill一次性一律引进来。不论代码有没有用到,只需目标环境不支持,就 require 进来。

2.当值为”usage”

这个配置下,babel会按需引入polyfill到每个文件中。意思是,只有需要用到某个polyfill时,才会require对应的polyfill

注意:一个文件只会require一次相同的polyfill

看下面这个例子:

// a.jsvar a = Promise.resolve();var b = Promise.resolve();// @babel/env 配置如下:[  "@babel/env",  {    "targets": {      "ie": 9    },    "useBuiltIns": "usage",    "corejs": 3  }]

babel输出结果如下:

"use strict";require("core-js/modules/es.object.to-string");require("core-js/modules/es.promise");var a = Promise.resolve();var b = Promise.resolve();

3.当值为false

babel不会自动增加polyfills,也不会转换import “core-js”
import “@babel/polyfill”

@babel/plugin-transform-runtime

为什么要使用 @babel/plugin-transform-runtime?

有下面两个起因:

  1. 默认情况下,babel会在需要的文件中插入许多小的帮助方法。当项目中存在多个文件中,这种小的帮助方法可能会重复。这是没有必要的。@babel/plugin-transform-runtime会将所有帮助函数,引用自 @babel/runtime,从而避免了帮助函数重复出现在了编译后的代码中。
  2. 假如直接import core-js, 其内置的诸如Promise,Map,Set会污染全局变量。@babel/plugin-transform-runtime 会创立一个沙箱环境,避免全局变量污染。

看一下不使用@babel/plugin-transform-runtime的编译结果

// a.jsvar a = async function () {};// b.jsvar b = async function () {};// babel配置如下:{  "presets": [    [      "@babel/env",      {        "targets": {          "ie": 9        },        "useBuiltIns": "usage",        "corejs": 3      }    ]  ]}

babel编译后输出如下:

// a.js"use strict";require("core-js/modules/es.object.to-string");require("core-js/modules/es.promise");require("regenerator-runtime/runtime");function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }var a = /*#__PURE__*/function () {  var _ref = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee() {    return regeneratorRuntime.wrap(function _callee$(_context) {      while (1) {        switch (_context.prev = _context.next) {          case 0:          case "end":            return _context.stop();        }      }    }, _callee);  }));  return function a() {    return _ref.apply(this, arguments);  };}();// b.js"use strict";require("core-js/modules/es.object.to-string");require("core-js/modules/es.promise");require("regenerator-runtime/runtime");function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }var b = /*#__PURE__*/function () {  var _ref = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee() {    return regeneratorRuntime.wrap(function _callee$(_context) {      while (1) {        switch (_context.prev = _context.next) {          case 0:          case "end":            return _context.stop();        }      }    }, _callee);  }));  return function a() {    return _ref.apply(this, arguments);  };}();

从上面的输出结果中可以看出:asyncGeneratorStep_asyncToGenerator 两个帮助函数代码重复了。

看下使用@babel/plugin-transform-runtime的编译结果

// a.jsvar a = async function () {};// b.jsvar b = async function () {};// babel配置如下:{  "presets": [    [      "@babel/env",      {        "targets": {          "ie": 9        }      }    ]  ],  "plugins": [    [      "@babel/plugin-transform-runtime",      {        "corejs": 3      }    ]  ]}

babel的编译结果如下:

// a.js"use strict";var _interopRequireDefault = require("@babel/runtime-corejs3/helpers/interopRequireDefault");var _regenerator = _interopRequireDefault(require("@babel/runtime-corejs3/regenerator"));var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime-corejs3/helpers/asyncToGenerator"));var a = /*#__PURE__*/function () {  var _ref = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee() {    return _regenerator.default.wrap(function _callee$(_context) {      while (1) {        switch (_context.prev = _context.next) {          case 0:          case "end":            return _context.stop();        }      }    }, _callee);  }));  return function a() {    return _ref.apply(this, arguments);  };}();// b.js"use strict";var _interopRequireDefault = require("@babel/runtime-corejs3/helpers/interopRequireDefault");var _regenerator = _interopRequireDefault(require("@babel/runtime-corejs3/regenerator"));var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime-corejs3/helpers/asyncToGenerator"));var b = /*#__PURE__*/function () {  var _ref = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee() {    return _regenerator.default.wrap(function _callee$(_context) {      while (1) {        switch (_context.prev = _context.next) {          case 0:          case "end":            return _context.stop();        }      }    }, _callee);  }));  return function b() {    return _ref.apply(this, arguments);  };}();

从上面的编译结果可以看出,使用 @babel/plugin-transform-runtime 编译后,重复的代码更少了。

总结:

推荐配置相似这样:

{  "presets": [    [      "@babel/env",      {        "targets": {          "ie": 9        }      }    ]  ],  "plugins": [    [      "@babel/plugin-transform-runtime",      {        "corejs": 3      }    ]  ]}

这样的配置,既可以转换es6及以上的语法,又能增加polyfill, 还不会污染全局环境,还能避免了重复注入相同的帮助函数。

优点简直不要太多。

推荐下个人公众号:

qrcode_for_gh_0af70036b598_258.jpg

说明
1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是摆设,本站源码仅提供给会员学习使用!
7. 如遇到加密压缩包,请使用360解压,如遇到无法解压的请联系管理员
开心源码网 » 探索下babel-preset-env和babel-plugin-transform-runtime的使用

发表回复