[轉] babel-present-env 與 babel-polyfill 學習總結


babelrc 配置文件

{
  "presets": [ [ "env", { "modules": false, "useBuiltIns": true, "targets": {"browsers": ["last 2 versions", "safari >= 7", "ie>=9"]} } ], "stage-0", "react" ], "plugins": [ "syntax-dynamic-import", [ "import", { "libraryName": "antd", "style": "css" } ] ] }
babel-present-env
根據你支持的環境自動決定適合你的 Babel 插件的 Babel preset。它使用了 compat-table 在沒有任何配置選項的情況下,babel-preset-env 與 babel-preset-latest(或者babel-preset-es2015,babel-preset-es2016和babel-preset-es2017一起)的行為完全相同。 它不會包含 stage-x 插件。env 將會支持我們認為最新版本的JavaScript的所有插件(過我們匹配在 babel-preset-latest 中所作的)。 這款preset能靈活決定加載哪些插件和polyfill,不過還是得開發者手動進行一些配置(targets)。 
babel-polyfill
  • polyfill 的意思

polyfill這個單詞翻譯成中文是墊片的意思,詳細點解釋就是桌子的桌腳有一邊矮一點,拿一個東西把桌子墊平。polyfill在代碼中的作用主要是用已經存在的語法和api實現一些瀏覽器還沒有實現的api,對瀏覽器的一些缺陷做一些修補。例如Array新增了includes方法,我想使用,但是低版本的瀏覽器上沒有,我就得做兼容處理

理解polyfill的意思之后,再來說說babel為什么存在polyfill。

因為babel的轉譯只是語法層次的轉譯,例如箭頭函數、解構賦值、class,對一些新增api以及全局函數 (例如:Promise)無法進行轉譯,這個時候就需要在代碼中引入babel-polyfill,讓代碼完美支持ES6+環境。 前面介紹的babel-node就會自動在代碼中引入babel-polyfill包。
  • 但很多時候我們並不會使用所有ES6+語法,全局添加所有墊片肯定會讓我們的代碼量上升,之后會介紹其他添加墊片的方式。
  • transform-runtime(transform-es2015-arrow-functions", //轉譯箭頭函數) 與 babel-runtime helpers 這種是按需進行 polyfill 無需全局引入 babel-polyfill 在一定程度上會減少代碼體積
比較transform-runtime與babel-polyfill引入墊片的差異:
使用runtime是按需引入,需要用到哪些polyfill,runtime就自動幫你引入哪些,不需要再手動一個個的去配置plugins,
只是引入的polyfill不是全局性的,有些局限性。
而且runtime引入的polyfill不會改寫一些實例方法,
比如Object和Array原型鏈上的方法,像前面提到的Array.protype.includes。 babel-polyfill就能解決runtime的那些問題,它的墊片是全局的,而且全能, 基本上ES6中要用到的polyfill在babel-polyfill中都有,它提供了一個完整的ES6+的環境。 babel官方建議只要不在意babel-polyfill的體積,最好進行全局引入,因為這是最穩妥的方式。 一般的建議是開發一些框架或者庫的時候使用不會污染全局作用域的babel-runtime, 而開發web應用的時候可以全局引入babel-polyfill避免一些不必要的錯誤, 而且大型web應用中全局引入babel-polyfill可能還會減少你打包后的文件體積(相比起各個模塊引入重復的polyfill來說)。 babel-polyfill 在項目代碼前插入所有的 polyfill 代碼,為你的程序打造一個完美的 es2015 運行環境。 babel 建議在網頁應用程序里使用 babel-polyfill,只要不在意它略有點大的體積(min 后 86kb),直接用它肯定是最穩妥的。 值得注意的是,因為 babel-polyfill 帶來的改變是全局的,所以無需多次引用,也有可能因此產生沖突, 所以最好還是把它抽成一個 common module,放在項目 的 vendor 里,或者干脆直接抽成一個文件放在 cdn 上。 回到應用開發。通過自動識別代碼引入 polyfill 來優化看來是不太靠譜的,那是不是就無從優化了呢? 並不是。還記得 babel 推薦使用的 babel-preset-env 么?它可以根據指定目標環境判斷需要做哪些編譯。 babel-preset-env 也支持針對指定目標環境選擇需要的 polyfill 了,只需引入 babel-polyfill,並在 babelrc 中聲明 useBuiltIns,babel 會將引入的 babel-polyfill 自動替換為所需的 polyfill。 
babel-present-env 的參數  useBuiltIns
1. 如果useBuiltIns為true,項目中必須引入babel-polyfill。 2. babel-polyfill只能被引入一次,如果多次引入會造成全局作用域的沖突。 做了個實驗,同樣的代碼,只是.babelrc配置中一個開啟了useBuiltIns,一個沒有,兩個js文件體積相差70k https://github.com/Shenfq/studyBabel/tree/master/7-babel-env useBuiltIns 可以根據之前的配置自行添加 polyfill,默認不開啟。 安裝 babel-polyfill 后只要引入一次就行:import "babel-polyfill"; 
  • webpack2 的 tree shanking 技術
tree-shaking 都是因為 ES6 modules 的靜態特性才得以實現的.
可以在編譯階段確定模塊依賴

要在項目中使用這一技術需將 .babelrc 的 env 選項的 modules設為false, 即不需要babel處理es6模塊,而交由webpack來處理

總結

  • 由於有了 babel-present-env 才可以手動按需配置所需要的 polyfill
  • babel-present-env 僅僅包括 babel-present-2015、2016、2017,不包括:babel-stage-x,也不包括 babel-polyfill
  • babel-present-env 僅僅轉換 新版的語法 如:箭頭函數,並不轉換新版api 如:Array.include
  • 轉換新版api及抹平瀏覽器之間的差異(兼容ie)需要 babel-polyfill

參考文章


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM