為什么要使用babel-polyfill?
Babel是一個廣泛使用的轉碼器,可以將ES6代碼轉為ES5代碼,從而可以在現有環境執行,所以我們可以用ES6編寫,而不用考慮環境支持的問題;
有些瀏覽器版本的發布早於ES6的定稿和發布,因此如果在編程中使用了ES6的新特性,而瀏覽器沒有更新版本,或者新版本中沒有對ES6的特性進行兼容,那么瀏覽器就會無法識別ES6代碼,例如IE9根本看不懂代碼寫的let和const是什么東西?只能選擇報錯,這就是瀏覽器對ES6的兼容性問題;
Babel默認只轉換新的JavaScript語法(syntax),如箭頭函數等,而不轉換新的API,比如Iterator、Generator、Set、Maps、Proxy、Reflect、Symbol、Promise等全局對象,以及一些定義在全局對象上的方法(比如Object.assign)都不會轉碼;因此我們需要polyfill;
因為這是一個 polyfill (它需要在源代碼之前運行),我們需要讓它成為一個 dependency(上線時的依賴),而不是一個 devDependency(開發時的依賴);
因為這是一個 polyfill (它需要在源代碼之前運行),我們需要讓它成為一個 dependency(上線時的依賴),而不是一個 devDependency(開發時的依賴);
1. 使用轉換插件: babel-plugin-transform-xxx
- 使用方法
- 缺啥補啥,在
package.json
添加所需的依賴babel-plugin-transform-xxx
- 在
.babelrc
中的plugins
項指定使用babel-plugin-transform-xxx
插件 - 代碼中不需要顯式
import/require
,.babelrc
中不需要指定useBuiltIns
,webpack.config.js
中不需要做額外處理,一切由babel插件完成轉換
- 缺啥補啥,在
- 優點
- 作用域是模塊,避免全局沖突
- 是按需引入,避免不必要引入造成及代碼臃腫
- 缺點
- 每個模塊內單獨引用和定義polyfill函數,造成了重復定義,使代碼產生冗余
配置完一個轉換插件后, 代碼中每個使用這個API的地方的代碼都會被轉換成使用
polyfill
中實現的代碼
2. 使用插件 babel-runtime 與 babel-plugin-tranform-runtime
相比方法1, 相當於抽離了公共模塊, 避免了重復引入, 從一個叫core.js
的庫中引入所需polyfill(一個國外大神用ES3寫的ES5+ polyfill)
- 使用方法
package.json
中添加依賴babel-plugin-tranform-runtime
以及babel-runtime
.babelrc
中配置插件:"plugins": ["transform-runtime"]
- 接下來, 代碼中可以直接使用ES6+的新特性,無需
import/require
額外東西,webpack
也不需要做額外配置
- 優點
- 無全局污染
- 依賴統一按需引入(polyfill是各個模塊共享的), 無重復引入, 無多余引入
- 適合用來編寫lib(第三方庫)類型的代碼
- 缺點
- 被
polyfill
的對象是臨時構造並被import/require
的,並不是真正掛載到全局 - 由於不是全局生效, 對於實例化對象的方法,如
[].include(x)
, 依賴於Array.prototype.include
仍無法使用
- 被
3. 全局babel-polyfill(不使用useBuiltIns)
- 使用方法
- 法3.1: (瀏覽器環境)單獨在html的
<head>
標簽中引入babel-polyfill.js
(CDN或本地文件均可) - 法3.2: 在
package.json
中添加babel-polyfill
依賴, 在webpack
配置文件增加入口: 如entry: ["babel-polyfill",'./src/app.js']
, polyfill將會被打包進這個入口文件中, 而且是放在文件最開始的地方 - 法3.3: 在
package.json
中添加babel-polyfill
依賴, 在webpack
入口文件頂部使用import/require
引入,如`import 'babel-polyfill'``
- 法3.1: (瀏覽器環境)單獨在html的
- 優點
- 一次性解決所有兼容性問題,而且是全局的,瀏覽器的
console
也可以使用
- 一次性解決所有兼容性問題,而且是全局的,瀏覽器的
- 缺點
- 一次性引入了ES6+的所有polyfill, 打包后的js文件體積會偏大
- 對於現代的瀏覽器,有些不需要polyfill,造成流量浪費
- 污染了全局對象
- 不適合框架或庫的開發
4. 全局babel-polyfill(使用babel-preset-env插件和useBuiltIns屬性)
- 使用方法
packge.json
引入依賴babel-preset-env
.babelrc
中使用配置preset-env
- 指定
useBuiltins
選項為true
- 指定瀏覽器環境或node環境, 配置需要兼容的瀏覽器列表
- 在
webpack
入口文件中使用import/require
引入polyfill
, 如import 'babel-polyfill'
- 以上配置完成之后,
babe
l會根據指定的瀏覽器兼容列表自動引入所有所需的polyfill
, 不管你代碼中有沒有使用
- .babelrc示例
{
"presets": [ ["env", { "modules": false, "targets": { "browsers": ["ie >=9"] }, "useBuiltIns": true, "debug": true }] ] }
- 優點
-
按需(按照指定的瀏覽器環境所需)引入
polyfill
, 一定程度上減少了不必要polyfill
的引入 -
配置簡單, 無需對
webpack
做額外的配置 -
注意:
- 不可與方法3混用,否則會引起沖突
- 全局方式要保證
polyfill
在所有其它腳本之前被執行(首行import
或者設置為html的第一個<head>
標簽)
-
5. polyfill.io
- 一個
CDN
方式提供的polyfill
, 可根據瀏覽器UserAgent
自動返回合適的polyfill
, 詳細內容自行google
作者:榮兒飛
鏈接:https://www.jianshu.com/p/3b27dfc6785c
來源:簡書
簡書著作權歸作者所有,任何形式的轉載都請聯系作者獲得授權並注明出處。