webpack 搭建文檔:https://webpack.eleven.net.cnhtml
首先要確認,@babel/polyfill 和 @babel/plugin-transform-runtime 各自均可以完成 ES 新 API 的轉譯,ES 新語法是由 @babel/preset-env 完成轉譯,因此,@babel/polyfill、@babel/plugin-transform-runtime 都需各自搭配 @babel/preset-env 一塊兒使用。翻閱、參考了大量資料,並在實際生產開發中驗證,兩者的配置、原理總結以下:
@babel/preset-env + @babel/polyfill
能夠轉譯語法、新 API,但存在污染全局問題;@babel/preset-env + @babel/plugin-transform-runtime + @babel/runtime-corejs2
,可按需導入,轉譯語法、新 API,且避免全局污染(babel7 中@babel/polyfill 是@babel/runtime-corejs2 的別名),可是檢測不到‘hello‘.includes(‘h‘)這種句法;@babel/polyfill 和@babel/runtime-corejs2 都使用了 core-js(v2)這個庫來進行 api 的處理。
core-js(v2)這個庫有兩個核心的文件夾,分別是 library 和 modules。@babel/runtime-corejs2 使用 library 這個文件夾,@babel/polyfill 使用 modules 這個文件夾。前端
library 和 modules 包含的文件基本相同,最大的不一樣是_export.js 這個文件:node
moduleswebpack
// core-js/modules/_exports.js var global = require('./_global'); var core = require('./_core'); var hide = require('./_hide'); var redefine = require('./_redefine'); var ctx = require('./_ctx'); var PROTOTYPE = 'prototype'; var $export = function (type, name, source) { var IS_FORCED = type & $export.F; var IS_GLOBAL = type & $export.G; var IS_STATIC = type & $export.S; var IS_PROTO = type & $export.P; var IS_BIND = type & $export.B; var target = IS_GLOBAL ? global : IS_STATIC ? global[name] || (global[name] = {}) : (global[name] || {})[PROTOTYPE]; var exports = IS_GLOBAL ? core : core[name] || (core[name] = {}); var expProto = exports[PROTOTYPE] || (exports[PROTOTYPE] = {}); var key, own, out, exp; if (IS_GLOBAL) source = name; for (key in source) { // contains in native own = !IS_FORCED && target && target[key] !== undefined; // export native or passed out = (own ? target : source)[key]; // bind timers to global for call from export context exp = IS_BIND && own ? ctx(out, global) : IS_PROTO && typeof out == 'function' ? ctx(Function.call, out) : out; // extend global if (target) redefine(target, key, out, type & $export.U); // export if (exports[key] != out) hide(exports, key, exp); if (IS_PROTO && expProto[key] != out) expProto[key] = out; } }; global.core = core; // type bitmap $export.F = 1; // forced $export.G = 2; // global $export.S = 4; // static $export.P = 8; // proto $export.B = 16; // bind $export.W = 32; // wrap $export.U = 64; // safe $export.R = 128; // real proto method for `library` module.exports = $export;
libraryes6
// core-js/library/_exports.js var global = require('./_global'); var core = require('./_core'); var ctx = require('./_ctx'); var hide = require('./_hide'); var has = require('./_has'); var PROTOTYPE = 'prototype'; var $export = function (type, name, source) { var IS_FORCED = type & $export.F; var IS_GLOBAL = type & $export.G; var IS_STATIC = type & $export.S; var IS_PROTO = type & $export.P; var IS_BIND = type & $export.B; var IS_WRAP = type & $export.W; var exports = IS_GLOBAL ? core : core[name] || (core[name] = {}); var expProto = exports[PROTOTYPE]; var target = IS_GLOBAL ? global : IS_STATIC ? global[name] : (global[name] || {})[PROTOTYPE]; var key, own, out; if (IS_GLOBAL) source = name; for (key in source) { // contains in native own = !IS_FORCED && target && target[key] !== undefined; if (own && has(exports, key)) continue; // export native or passed out = own ? target[key] : source[key]; // prevent global pollution for namespaces exports[key] = IS_GLOBAL && typeof target[key] != 'function' ? source[key] // bind timers to global for call from export context : IS_BIND && own ? ctx(out, global) // wrap global constructors for prevent change them in library : IS_WRAP && target[key] == out ? (function (C) { var F = function (a, b, c) { if (this instanceof C) { switch (arguments.length) { case 0: return new C(); case 1: return new C(a); case 2: return new C(a, b); } return new C(a, b, c); } return C.apply(this, arguments); }; F[PROTOTYPE] = C[PROTOTYPE]; return F; // make static versions for prototype methods })(out) : IS_PROTO && typeof out == 'function' ? ctx(Function.call, out) : out; // export proto methods to core.%CONSTRUCTOR%.methods.%NAME% if (IS_PROTO) { (exports.virtual || (exports.virtual = {}))[key] = out; // export proto methods to core.%CONSTRUCTOR%.prototype.%NAME% if (type & $export.R && expProto && !expProto[key]) hide(expProto, key, out); } } }; // type bitmap $export.F = 1; // forced $export.G = 2; // global $export.S = 4; // static $export.P = 8; // proto $export.B = 16; // bind $export.W = 32; // wrap $export.U = 64; // safe $export.R = 128; // real proto method for `library` module.exports = $export;
例如對Promise的轉譯,@babel/polyfill和@babel/runtime-corejs2的轉譯方式差別以下:web
var p = new Promise(); // @babel/polyfill require("core-js/modules/es6.promise"); var p = new Promise(); // @babel/runtime-corejs2 var _interopRequireDefault = require("@babel/runtime-corejs2/helpers/interopRequireDefault"); var _promise = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/promise")); var a = new _promise.default();
綜合上面的分析,得出結論:api
若是是本身的應用: @babel/preset-env + @babel/polyfill
promise
根據useBuiltIns參數肯定如何使用@babel/polyfill,具體參數設置總結以下:安全
useBuiltIns
設置爲entry
比較不錯,推薦使用。 import '@babel/polyfill'
,或在webpack的入口entry中寫入模塊@babel/polyfill
,會將browserslist環境不支持的全部墊片都導入;‘hello‘.includes(‘h‘)
這種句法,足夠安全且代碼體積不是特別大!useBuiltIns
設置爲usage
。 node_modules/
目錄,若是使用到的第三方包有個別未作好ES6轉譯,有遇到bug的可能性,而且檢測不到‘hello‘.includes(‘h‘)
這種句法。useBuiltIns
設置爲false
比較不錯。 import '@babel/polyfill'
,或在webpack的入口entry中寫入模塊@babel/polyfill
,會將@babel/polyfill整個包所有導入;須要安裝的所有依賴:babel
yarn add babel-loader@8 @babel/core @babel/preset-env -D yarn add @babel/polyfill
.babelrc配置文件
{ "presets": [ [ "@babel/preset-env", { "modules": false, // 推薦 "useBuiltIns": "entry", // 推薦 "corejs": 2, // 新版本的@babel/polyfill包含了core-js@2和core-js@3版本,因此須要聲明版本,不然webpack運行時會報warning,此處暫時使用core-js@2版本(末尾會附上@core-js@3怎麼用) } ] ], "plugins": [] }
若是是開發第三方類庫: @babel/preset-env + @babel/plugin-transform-runtime + @babel/runtime-corejs2
(或者,不作轉碼處理,提醒使用者本身作好兼容處理也能夠)。
須要安裝的所有依賴:
yarn add babel-loader@8 @babel/core @babel/preset-env @babel/plugin-transform-runtime -D yarn add @babel/runtime-corejs2
.babelrc配置文件
{ "presets": [ [ "@babel/preset-env", { "modules": false, } ] ], "plugins": [ [ "@babel/plugin-transform-runtime", { "corejs": 2 // 推薦 } ] ] }