詳解如何添加babel?polyfill
正文
由于 Babel 7.4 之后不再推薦使用 @babel/polyfill
,而 @babel/preset-env
和 plugin-transform-runtime
二者都可以設(shè)置 corejs
來(lái)處理 polyfill
。
@babel/polyfill
廢棄的主要原因有:
- 此包僅僅是引入了 stable core-js 和 regenerator-runtime/runtime,其中后者可以使用插件 @babel/plugin-transform-regenerator 代替。
- 此包不能從core-js@2 平滑過渡到 core-js@3。
Babel 簡(jiǎn)介
簡(jiǎn)單來(lái)說,Babel
是一個(gè)編譯器,主要用于將采用 ECMAScript 2015+
語(yǔ)法編寫的代碼轉(zhuǎn)換為向后兼容的 JavaScript
語(yǔ)法,以便能夠運(yùn)行在新舊版本的瀏覽器等各個(gè)環(huán)境中。而 Babel 代碼轉(zhuǎn)換功能以 plugin
的方式實(shí)現(xiàn),plugin
就是小型的 JavaScript 程序。
preset
可以被看作是一組 Babel 插件或 options
配置的可共享模塊。
- plugins 在 presets 前運(yùn)行;
- plugins 從前往后順序執(zhí)行;
- presets 根據(jù)排列順序倒序執(zhí)行;
babel 主要實(shí)現(xiàn)的兩個(gè)功能:
- 轉(zhuǎn)換新語(yǔ)法。將新版 js 語(yǔ)法用舊版語(yǔ)法實(shí)現(xiàn),從而在對(duì)應(yīng)環(huán)境中運(yùn)行,比如箭頭函數(shù);
轉(zhuǎn)換新 API。為舊版運(yùn)行時(shí)打補(bǔ)丁(也被稱為polyfill),從而使用在新版 js 中定義但在舊版運(yùn)行時(shí)提供的功能,包括三類:
- 新定義的內(nèi)置對(duì)象,例如
Promise
- 原有內(nèi)置對(duì)象新添加的靜態(tài)方法,例如
Array.from
- 原有內(nèi)置對(duì)象新添加的實(shí)例方法,例如
Array.prototype.includes
- 新定義的內(nèi)置對(duì)象,例如
preset-env
preset-env
既可以轉(zhuǎn)換新語(yǔ)法,也可以通過配置轉(zhuǎn)換新的 API
。preset-env
的 polyfill
會(huì)污染全局環(huán)境。
target
這個(gè)字段可以填寫 browserslist
的查詢字符串,官方推薦使用 .browserslistrc
文件去指明編譯的 target
,這個(gè)配置文件還可以和autoprefixer
、stylelint
等工具一起共享配置。所以不推薦在.babelrc
的preset-env
配置中直接使用targets
進(jìn)行配置。
如果需要單獨(dú)在這里配置targets
的話,preset-env
中指明ignoreBrowserslistConfig
為true
則忽略.browserslistrc
的配置項(xiàng)。
useBuiltIns
是否使用其polyfill
功能(全局環(huán)境的core-js)。有三個(gè)值:
false
:默認(rèn)值。在不主動(dòng)import
的情況下不使用preset-env
來(lái)實(shí)現(xiàn)polyfills
,只使用其默認(rèn)的語(yǔ)法轉(zhuǎn)換功能。如果使用默認(rèn)值false
,則應(yīng)該避免在入口文件引入polyfill
,使得打包體積過大。
entry
:需要手動(dòng)在入口處引入 polyfill
,根據(jù)瀏覽器目標(biāo)環(huán)境(targets
)的配置,引入全部瀏覽器暫未支持的 polyfill
模塊,無(wú)論在項(xiàng)目中是否使用到。
import "core-js/proposals/string-replace-all"
usage
: 不需要手動(dòng)在入口文件引入polyfill
,Babel
將會(huì)根據(jù)代碼使用情況自動(dòng)注入polyfill
,如此一來(lái)在打包的時(shí)候?qū)?huì)相對(duì)地減少打包體積。
corejs
配置core-js,默認(rèn)值"2.0"。此選項(xiàng)僅在與 useBuiltIns: usage
或 useBuiltIns: entry
一起使用時(shí)有效。
core-js: JavaScript 的模塊化標(biāo)準(zhǔn)庫(kù),包含 Promise
、Symbol
、Iterator
和許多其他的特性,它可以讓你僅加載必需的功能。
- version: 【string】版本號(hào);
- proposals: 【boolean】是否實(shí)現(xiàn)提案中的特性;
//?.babelrc { "presets":?[???? [?????? "@babel/preset-env",?????? {???????? "targets":?{?????????? "chrome":?"80"?//?推薦使用?.browserslistrc???????? },???????? "useBuiltIns":?"usage",???????? "corejs":?{?????????? "version":?3,?//?2?和?3?版本都需要手動(dòng)安裝庫(kù):yarn?add?core-js@3? "proposals":?false???????? }?????? }???? ]?? ] }
plugin-transform-runtime
plugin-transform-runtime
主要做了三件事:
- 當(dāng)開發(fā)者使用異步或生成器的時(shí)候,自動(dòng)引入
@babel/runtime/regenerator
,開發(fā)者不必在入口文件做額外引入; 動(dòng)態(tài)引入
polyfill
,提供沙盒環(huán)境,避免全局環(huán)境的污染;如果直接導(dǎo)入 core-js 或 @babel/polyfill 以及它提供的 Promise、Set 和 Map 等內(nèi)置組件,這些都會(huì)污染全局。雖然這不影響應(yīng)用程序或命令行工具,但如果代碼是要發(fā)布給其他人使用的庫(kù),或者無(wú)法準(zhǔn)確控制代碼將運(yùn)行的環(huán)境,則會(huì)出現(xiàn)問題。
- 所有 helpers 幫助模塊都將引用模塊 @babel/runtime,以避免編譯輸出中的重復(fù),減小打包體積;
corejs
配置值:false, 2, 或者 { version: number, proposals: boolean }
,默認(rèn)值 false。
corejs | 安裝建議 |
---|---|
false | npm install --save @babel/runtime |
2 | npm install --save @babel/runtime-corejs2 |
3 | npm install --save @babel/runtime-corejs3 |
helpers
配置值 boolean 類型,默認(rèn)值 true。
是否用對(duì) moduleName 的調(diào)用替換內(nèi)聯(lián) Babel 幫助程序(classCallCheck、extends等)。
regenerator
配置值 boolean 類型,默認(rèn)值 true。
是否將生成器函數(shù)轉(zhuǎn)換為使用不污染全局范圍的再生器運(yùn)行時(shí)。
useESModules
配置值 boolean 類型,默認(rèn)值 false。
啟用后,轉(zhuǎn)換將使用幫助程序,而不是@babel/plugin-transform-modules-commonjs。這允許在 webpack 等模塊系統(tǒng)中進(jìn)行較小的構(gòu)建,因?yàn)樗恍枰A?commonjs 語(yǔ)義。
使用場(chǎng)景與實(shí)例分析
@babel/preset-env
和 plugin-transform-runtime
二者都可以設(shè)置使用 corejs
來(lái)處理polyfill
,二者各有使用場(chǎng)景,在項(xiàng)目開發(fā)和類庫(kù)開發(fā)的時(shí)候可以使用不同的配置。
不要同時(shí)為二者配置 core-js,以免產(chǎn)生復(fù)雜的不良后果。
項(xiàng)目開發(fā)
useBuiltIns
使用 usage
。plugin-transform-runtime
只使用其移除內(nèi)聯(lián)復(fù)用的輔助函數(shù)的特性,減小打包體積。
{ "presets": [ [ "@babel/preset-env", { "useBuiltIns": "usage", "corejs": { "version": 3, "proposals": false } } ] ], "plugins": [ [ "@babel/plugin-transform-runtime", { "corejs": false } ] ] }
類庫(kù)開發(fā)
類庫(kù)開發(fā)盡量不使用污染全局環(huán)境的 polyfill
,因此 @babel/preset-env
只發(fā)揮語(yǔ)法轉(zhuǎn)換的功能, polyfill
由 plugin-transform-runtime
來(lái)處理,推薦使用 core-js@3
,并且不使用未進(jìn)入規(guī)范的特性。
{ "presets": ["@babel/preset-env"], "plugins": [ [ "@babel/plugin-transform-runtime", { "corejs": { "version": 3, "proposals": false }, "useESModules": true } ] ] }
打包分析
測(cè)試代碼如下:
// syntax class Person {} typeof Person const array = [1, 2, 3] const fun = () => {} // api const a = Array.isArray([3, 5, 8]) const b = array.map(itm => itm * 2) const p1 = Promise.resolve(true) const p2 = Promise.reject(false) Promise.allSettled([p1, p2]).then(() => { console.log('then') }).catch(() => { console.log('catch') }).finally(() => { console.log('finally') })
通過 preset-env 配置 core-js:
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); require("core-js/modules/es.array.is-array.js"); require("core-js/modules/es.array.map.js"); require("core-js/modules/es.object.to-string.js"); require("core-js/modules/es.promise.js"); require("core-js/modules/es.promise.finally.js"); require("core-js/modules/es.array.iterator.js"); require("core-js/modules/esnext.promise.all-settled.js"); require("core-js/modules/es.string.iterator.js"); require("core-js/modules/web.dom-collections.iterator.js"); var _typeof2 = _interopRequireDefault(require("@babel/runtime/helpers/typeof")); var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass")); var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck")); // syntax var Person = /*#__PURE__*/(0, _createClass2["default"])(function Person() { (0, _classCallCheck2["default"])(this, Person); }); (0, _typeof2["default"])(Person); var array = [1, 2, 3]; var fun = function fun() {}; // api var a = Array.isArray([3, 5, 8]); var b = array.map(function (itm) { return itm * 2; }); var p1 = Promise.resolve(true); var p2 = Promise.reject(false); Promise.allSettled([p1, p2]).then(function () { console.log('then'); })["catch"](function () { console.log('catch'); })["finally"](function () { console.log('finally'); });
通過 plugin-transform-runtime 配置 core-js:
"use strict"; var _interopRequireDefault = require("@babel/runtime-corejs3/helpers/interopRequireDefault"); var _isArray = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/array/is-array")); var _map = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/instance/map")); var _promise = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/promise")); var _typeof2 = _interopRequireDefault(require("@babel/runtime-corejs3/helpers/typeof")); var _createClass2 = _interopRequireDefault(require("@babel/runtime-corejs3/helpers/createClass")); var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime-corejs3/helpers/classCallCheck")); // syntax var Person = /*#__PURE__*/(0, _createClass2["default"])(function Person() { (0, _classCallCheck2["default"])(this, Person); }); (0, _typeof2["default"])(Person); var array = [1, 2, 3]; var fun = function fun() {}; // api var a = (0, _isArray["default"])([3, 5, 8]); var b = (0, _map["default"])(array).call(array, function (itm) { return itm * 2; }); var p1 = _promise["default"].resolve(true); var p2 = _promise["default"].reject(false); _promise["default"].allSettled([p1, p2]).then(function () { console.log('then'); })["catch"](function () { console.log('catch'); })["finally"](function () { console.log('finally'); });
通過打包后代碼分析,以 preset-env 的方式會(huì)引入不必須的 polyfill,以 plugin-transform-runtime 的方式只會(huì)引入當(dāng)前頁(yè)面所需的 polyfill。
以上就是詳解如何添加 babel polyfill的詳細(xì)內(nèi)容,更多關(guān)于添加 babel polyfill的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
vue長(zhǎng)列表優(yōu)化之虛擬列表實(shí)現(xiàn)過程詳解
前端的業(yè)務(wù)開發(fā)中會(huì)遇到不使用分頁(yè)方式來(lái)加載長(zhǎng)列表的需求,下面這篇文章主要給大家介紹了關(guān)于vue長(zhǎng)列表優(yōu)化之虛擬列表實(shí)現(xiàn)的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-08-08從0到1搭建element后臺(tái)框架優(yōu)化篇(打包優(yōu)化)
這篇文章主要介紹了從0到1搭建element后臺(tái)框架優(yōu)化篇(打包優(yōu)化),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來(lái)看看吧2019-05-05詳解vue-cli本地環(huán)境API代理設(shè)置和解決跨域
這篇文章主要介紹了詳解vue-cli本地環(huán)境API代理設(shè)置和解決跨域,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-09-09Nginx配置Vue項(xiàng)目,無(wú)法按路徑跳轉(zhuǎn)及刷新404的解決方案
這篇文章主要介紹了Nginx配置Vue項(xiàng)目,無(wú)法按路徑跳轉(zhuǎn)及刷新404的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-06-06vue項(xiàng)目之頁(yè)面class不生效問題及解決
這篇文章主要介紹了vue項(xiàng)目之頁(yè)面class不生效問題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-07-07詳解Vue實(shí)現(xiàn)鏈接生成二維碼并支持下載
在現(xiàn)代 Web 應(yīng)用中,快速分享鏈接是一項(xiàng)常見需求,二維碼作為一種簡(jiǎn)潔的分享方式,受到了廣泛歡迎,所以本文將介紹如何使用 Vue 純前端技術(shù)實(shí)現(xiàn)動(dòng)態(tài)生成鏈接二維碼的方法,需要的可以參考下2024-03-03vue實(shí)現(xiàn)動(dòng)態(tài)添加數(shù)據(jù)滾動(dòng)條自動(dòng)滾動(dòng)到底部的示例代碼
本篇文章主要介紹了vue實(shí)現(xiàn)動(dòng)態(tài)添加數(shù)據(jù)滾動(dòng)條自動(dòng)滾動(dòng)到底部的示例代碼,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-07-07