Babel基礎知識整理


Babel是一個JavaScript編譯器
Babel 是一個工具鏈,主要用於將 ECMAScript 2015+ 版本的代碼轉換為向后兼容的 JavaScript 語法,以便能夠運行在當前和舊版本的瀏覽器或其他環境中。下面列出的是 Babel 能為你做的事情:
  • 語法轉換
  • 通過 Polyfill 方式在目標環境中添加缺失的特性 (通過 @babel/polyfill 模塊)
  • 源碼轉換 (codemods)
Presets(預設)
 
一、@babel/preset-env (官方preset)
 
 作用:預設目標環境,添加我們需要的預設環境
        
     babel-preset-env將基於你的實際瀏覽器及運行環境,自動的確定babel插件及polyfill,編譯ES2015及此版本以上的語言,在沒有配置項的情況下, babel-preset-env表現的同 babel-preset-latest一樣(或者可以說同 babel-preset-es2015, babel-preset-es2016, and babel-preset-es2017結合到一起,表現的一致)。
 
1 {
2     "presets": ["@babel/preset-env"]
3 }
4  
5 {
6     "presets": ["@babel/preset-env”,option]
7 }
 
常用配置字段:
 
1、targets: String | Array | { [String]: string } 。默認為{}
 
          這一屬性說明了當前的項目的適用環境。可以編寫字符串的內容,作為boswerlist的遍歷條件。例如:"targets": "> 0.25%, not dead" 或者也可以使一個對象。來設置對於每一個瀏覽器最低版本的控制。例如:{ "targets": { "chrome": "58", "ie": "11" } },其中的瀏覽器關鍵字從如下之中選取:chrome, opera, edge, firefox, safari, ie, ios, android, node, electron
 
2、 boswerlist:
    是在不同的前端工具之間共用目標瀏覽器和 node 版本的配置工具, browserslist可以在babel之中配置,來告訴babel具體轉化代碼的規則。有三種配置方式:
  • 在.babelrc或者babel.config.js中去配置
 1 {
 2   "presets": [
 3     [
 4       "@babel/preset-env",
 5       {
 6         "targets": {
 7           "node": "4",
 8           "chrome": "58",
 9           "ie": "11"
10         }
11       }
12     ]
13   ]
14 }
  • 在package.json 里面增加如下配置        
1 { 
2     "browserslist": [ 
3         "last 1 version", "> 1%",
4          "maintained node versions", "not dead" 
5     ]
6 }        
  • 在工程的根目錄下存在.browerslistrc配置文件
  
# 注釋是這樣寫的,以#號開頭 
last 1 version 
> 1%
maintained node versions 
not dead
 
配置文件來源:
browerslist 將使用如下配置文件限定的的瀏覽器和 node 版本范圍:
  • 工具 options,例如 Autoprefixer 工具配置中的 browsers 屬性。
  • BROWERSLIST 環境變量。
  • 當前目錄或者上級目錄的browserslist配置文件。
  • 當前目錄或者上級目錄的browserslistrc配置文件。
  • 當前目錄或者上級目錄的package.json配置文件里面的browserslist配置項(推薦)。
  • 如果上述的配置文件缺失或者其他因素導致未能生成有效的配置,browserslist 將使用默認配置> 0.5%, last 2 versions, Firefox ESR, not dead。
 
 
實踐經驗:
  • 僅僅當你在特定瀏覽器上開發類似於信息亭之類的 web app 的時候,才可以用類似last 2 Chrome versions的查詢條件來鎖定特別具體的瀏覽器品牌和版本。市面上有各種各樣的瀏覽器,同時瀏覽器的版本碎片化也很嚴重,如果你在開發一款通用的 webapp,那就應該考慮瀏覽器多樣性導致的兼容問題。
  • 如果你不想用 browserslsit 的默認設置,推薦使用last 1 version, not dead > 0.2%(或者> 1% in US,> 1% in my stats).僅僅使用last n versions 將添加太多的廢棄瀏覽器到工程里面來,同時也並沒有有效的覆蓋那些占有率仍然很高的老版本瀏覽器。
  • 不移除某些瀏覽器,是因為你不了解它們的分布。Opera mini 在非洲有一億用戶,全球范圍內,它也比 微軟的 Edge 瀏覽器更加流行。QQ 瀏覽器的使用量比桌面端的火狐和 Safari 瀏覽器加起來還多。
 
查詢條件列表:
可以用如下查詢條件來限定瀏覽器和 node 的版本范圍(大小寫不敏感):
  • > 5%: 基於全球使用率統計而選擇的瀏覽器版本范圍。>=,<,<=同樣適用。
  • > 5% in US : 同上,只是使用地區變為美國。支持兩個字母的國家碼來指定地區。
  • > 5% in alt-AS : 同上,只是使用地區變為亞洲所有國家。這里列舉了所有的地區碼。
  • > 5% in my stats : 使用定制的瀏覽器統計數據
  • cover 99.5% : 使用率總和為99.5%的瀏覽器版本,前提是瀏覽器提供了使用覆蓋率。
  • cover 99.5% in US : 同上,只是限制了地域,支持兩個字母的國家碼。
  • cover 99.5% in my stats :使用定制的瀏覽器統計數據
  • maintained node versions :所有還被 node 基金會維護的 node 版本。
  • node 10 and node 10.4 : 最新的 node 10.x.x 或者10.4.x 版本。
  • current node :當前被 browserslist 使用的 node 版本。
  • extends browserslist-config-mycompany :來自browserslist-config-mycompany包的查詢設置
  • ie 6-8 : 選擇一個瀏覽器的版本范圍。
  • Firefox > 20 : 版本高於20的所有火狐瀏覽器版本。>=,<,<=同樣適用。
  • ios 7 :ios 7自帶的瀏覽器。
  • Firefox ESR :最新的火狐 ESR(長期支持版) 版本的瀏覽器。
  • unreleased versions or unreleased Chrome versions : alpha 和 beta 版本。
  • last 2 major versions or last 2 ios major versions :最近的兩個發行版,包括所有的次版本號和補丁版本號變更的瀏覽器版本。
  • since 2015 or last 2 years :自某個時間以來更新的版本(也可以寫的更具體since 2015-03或者since 2015-03-10)
  • dead :通過last 2 versions篩選的瀏覽器版本中,全球使用率低於0.5%並且官方聲明不在維護或者事實上已經兩年沒有再更新的版本。目前符合條件的有 IE10,IE_Mob 10,BlackBerry 10,BlackBerry 7,OperaMobile 12.1。
  • last 2 versions :每個瀏覽器最近的兩個版本。
  • last 2 Chrome versions :chrome 瀏覽器最近的兩個版本。
  • defaults :默認配置> 0.5%, last 2 versions, Firefox ESR, not dead。
  • not ie <= 8 : 瀏覽器范圍的取反。
  • 可以添加not在任和查詢條件前面,表示取反
 
            注意事項:
                Browserslist 會處理瀏覽器的每個版本,所以應該避免配置這樣的查詢條件Firefox > 0.多個查詢條件組和
            在一起之后,其之間的的覆蓋是以OR 的方式,而是不是AND,也就是說只要瀏覽器版本符合篩選條件里面的
            一種即可。
                所有的查詢條件均基於 Can I Use的支持列表。例如:last 3 ios versions 可能會返回8.4, 9.2, 9.3(混合了
            主版本和次版本),然而last 3 Chrome versions可能返回50, 49, 48(只有主版本),總之一切以 CanIUse網
            站收集的瀏覽器版本數據為准。
    
            不同環境的差異化配置:
"browserslist": {
    "production": [
      "> 1%",
      "ie 10"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version"
    ]
  }
 
3、useBuiltIns : "usage"| "entry"| false,默認為false。
 此選項配置 @babel/preset-env如何處理 polyfillusageentry選項配置上都是增加按需引入的功能。
  • “useBuiltIns”: “usage"
    在文件需要的位置單獨按需引入,可以保證在每個bundler中只引入一份。當前模式類似於@babel/plugin-transform-runtime,polyfill局部使用,制造一個沙盒環境,不造成全局污染
  • “useBuiltIns”: “entry”
    在項目入口引入一次(多次引入會報錯),插件@babel/preset-env會將把@babel/polyfill根據實際需求打散,只留下必須的,例如:
     In
    import "@babel/polyfill”;
 
   Out (實際引入取決於環境不同)
  import "core-js/modules/es6.promise";
  import "core-js/modules/es7.string.pad-start";
  import "core-js/modules/es7.string.pad-end";
  import "core-js/modules/es7.array.includes";
 
 
4、modules
        選項用於模塊轉化規則設置,可選配置包括:"amd" | "umd" | "systemjs" | "commonjs" | false, 默認使用 "commonjs"。即,將代碼中的ES6的import轉為require。
        如果你當前的webpack構建環境是2.x/3.x,推薦將modules設置為false,即交由 Webpack 來處理模塊化,通過其 TreeShaking 特性將有效減少打包出來的 JS 文件大小。這部分參考這里的回答: ECMAScript 6 的模塊相比 CommonJS 的require (...)有什么優點?
 
5、include :Array<string|RegExp>,默認為[]
轉譯時必須包含的插件
 
6、exclude: Array<string|RegExp>,默認為[]
轉譯時排除在外的插件
 
二、@babel/preset-react(官方preset)
 
作用:react 語法轉譯
 
1、默認包含的插件
此 preset 始終包含以下插件:
以及以下開發環境下的選擇輔助開發插件:
 
PS:一般使用該預設都是默認值,不需要單獨配置插件
 
配置參數:
  • pragma
  string 類型,默認值為 React.createElement。編譯 JSX 表達式時替用於換所使用的函數(function)。
  • pragmaFrag
  string 類型,默認值為 React.Fragment。編譯 JSX 片段時用於替換所用的組件。
  • useBuiltIns
  boolean 類型,默認值為 false。當插件需要某項功能時,此參數用於確定是使用內置功能還是通過 polyfill 來模擬。
  • development
  boolean 類型,默認值為 false。用於確定是否開啟用於輔助開發的插件,例如  @babel/plugin-transform-react-jsx-self 和  @babel/plugin-transform-react-jsx-source。當與  env 參數 配置或  js 配置文件 一同使用時會非常有用。
  • throwIfNamespace
  boolean 類型,默認值為 true。如果使用了 XML 命名空間標簽,此參數用於設置是否拋出錯誤。例如:<f:image />。雖然 JSX 規范允許這樣做,但是默認情況下是被禁止的,因為 React 的 JSX 目前並不支持這  種方式。
 
 
三、@babel/preset-stage-x
 
作用:可以將處於某一階段的js語法編譯為正式版本的js代碼
 
1、stage-X: 指處於某一階段的js語言提案。
    提案共分為5個階段:
  •  stage-0:稻草人-只是一個大膽的想法
  •  stage-1:提案-初步嘗試
  •  stage-2:初稿-完成初步規范
  •  stage-3:候選-完成規范和瀏覽器初步實現
  •  stage-4:完成-將被添加到下一年發布
  如果不知道需要哪個stage-x的話,直接引入stage-0,stage-0包含所有stage-1所有插件,stage-1包含所有stage-2所有插件,stage-2包含所有stage-3所有插件(每個stage包含的插件就不列了,感興趣可以自行百度,可以參考看下 http://www.bubuko.com/infodetail-1895965.html
 
PS: babel-preset-stage-4已經整合入Presets不單獨發布了
 

plugins(插件)

    Babel 是一個編譯器(輸入源碼 => 輸出編譯后的代碼)。就像其他編譯器一樣,編譯過程分為三個階段:解析、轉換和打印輸出。
    現在,Babel 雖然開箱即用,但是什么動作都不做。它基本上類似於 const babel = code => code; ,將代碼解析之后再輸出同樣的代碼。如果想要 Babel 做一些實際的工作,就需要為其添加插件。
    除了一個一個的添加插件,你還可以以  preset 的形式啟用一組插件。
 
一、轉換插件
 
作用:這些插件用於轉換你的代碼。(轉換插件將啟用相應的語法插件,因此你不必同時指定這兩種插件。)
 
1、ES3
2、ES5
3、ES2015(ES6)
4、ES2016
5、ES2017
6、ES2018
7、Modules
8、Experimental
9、Minification
10、React
11、其他
二、語法插件
    
  這些插件只允許 Babel 解析(parse) 特定類型的語法(而不是轉換)。(注意:轉換插件會自動啟用語法插件。因此,如果你已經使用了相應的轉換插件,則不需要指定語法插件。)
    
{ 
    "parserOpts": { 
        "plugins": [
            "jsx", 
            "flow"
         ] 
    } 
}            
 
三、插件/Preset路徑
    
    如果插件再 npm 上,你可以輸入插件的名稱,babel 會自動檢查它是否已經被安裝到 node_modules 目錄下
{ "plugins": ["babel-plugin-myPlugin"] }
    你還可以指定插件的相對/絕對路徑。
{ "plugins": ["./node_modules/asdf/plugin"] }
 
四、插件的短名稱
    
    如果插件名稱的前綴為 babel-plugin-,你還可以使用它的短名稱:
1 { "plugins": [ 
2         "myPlugin”,
3         "babel-plugin-myPlugin" // 兩個插件實際是同一個
4     ] 
5 }
   
     這也適用於帶有冠名(scope)的插件:
  
1 { "plugins": [ 
2         "@org/babel-plugin-name”, 
3         "@org/name" // 兩個插件實際是同一個 
4     ] 
5 }
 
五、插件順序
  • Plugin 會運行在 Preset 之前。
  • Plugin 會從第一個開始順序執行。ordering is first to last.
  • Preset 的順序則剛好相反(從最后一個逆序執行)。
 
常用插件說明
 
1、babel-core //必備的核心庫
2、babel-loader //webpack loader配置必備
3、babel-preset-env //有了它,你不再需要添加2015、2016、2017,全都支持
4、babel-preset-stage-0 //有了它,你不再需要添加stage-1,stage-2,stage-3,默認向后支持
5、babel-plugin-transform-runtime 、babel-runtime   //支持helpers,polyfill,regenerator配置
     
   babel-plugin-transform-runtime該插件主要做了三件事
  • 自動轉換generators/async
  • 使用core-js來按需給內置類型打上polyfill。(這一點和useBuiltIns:'usage'一樣)
  • 通過helpers 選項自動移除嵌入的babel helper,並且用module引用來代替。否則每個文件中都會加入這些inline babel helper,造成代碼冗余。默認為ture
      @babel/runtime@babel/polyfill 雖然都是為內置類型打上墊片,但是 @babel/runtime是在模塊內起作用,不會污染全局的Promise,Map...。所以實例的方法不會被 polyfill
     但是如果運行環境很low,比如比如說Android一些老機子,而你有需要大量使用 Promise、Object.assign、Array.find之類的全局對象或者其所屬方法,那么使用 babel-polyfill,絕對是一勞永逸。
     接着,再來說說 babel-runtime,相對而言,它的處理方式比較溫柔,套用步步高的廣告詞就是哪里需要加哪里,比如說你需要 Promise,你只需要 import Promise from 'babel-runtime/core-js/promise'即可,這樣不僅避免污染全局對象,而且可以減少不必要的代碼。
     不過,如果N個文件都需要 Promise,難道得一個個文件的加 import Promise from 'babel-runtime/core-js/promise'么,顯然不是,Babel已經為這樣情況考慮過了,只需要使用 babel-plugin-transform-runtime就可以輕松的幫你省去手動import的痛苦,而且,它還做了公用方法的抽離,哪怕你有100個模塊使用了 Promise,但是 promisepolyfill僅僅存在1份,所有要的地方都是引用一地方,具體的配置參考如下:
 1 // .babelrc
 2 {
 3   "presets": [
 4     "env",
 5     "stage-0"
 6   ],
 7   "plugins": [
 8     "transform-runtime"
 9   ],
10   "comments": false
11 }
    
   @babel/plugin-transform-runtime 還可以和 preset-env中的 useBuiltIns一起使用,作用的順序按照plugins --> presets 的順序,也就是先使用 @babel/plugin-transform-runtime 打上墊片,然后再使用 @babel/polyfill 再打上一次墊片。
 
如果使用react:
1、babel-plugin-transform-decorators-legacy //支持修飾符語法 @connect
2、babel-preset-react //支持解析react語法,如果使用vue把react替換成vue就好
 
如果需要熱更新:
1、react-hot-loader //雖然它長得不像babel,但是它也需要在babelrc做配置
 
 
最后總結
 
主要幾個配置
  • presets : 預設,插件的集合,倒序執行
  • plugins : 插件,先執行插件,在執行預設,順序執行
  • ignore : 忽略的文件
  • minify : 壓縮代碼
  • common : 是否需要注釋
  • env : 設置不同的環境,應用不同的配置,配置取值:BABEL_ENV,如若沒有取 NODE_ENV 的值,默認為 development.
常見預設
  • env  : 用於替換 es2015 /  es2016 / es2017 的預設。根據環境引入插件
  • react :react的插件集合
  • react-optimize : react 代碼優化,如去除 propsType 減少生產上面代碼
  • stage-x :草案代碼插件集合
  • flow : flow 插件集合
  • minify : 代碼優化的集合
  • typescript : typescript 插件集合
常用插件
  • transform-async-to-generator : 異步函數 async/await 插件
  • transform-decorators-leagacy : 裝飾器插件
  • syntax-dynamic-import :import() 插件
  • transform-runtime : 輔助器插件,用於ployfill
  • transform-object-rest-spread : 用於合並 var test = {a:1,b2};var t = {...test,n:1}
  • transform-funciton-bind : 用於編譯 obj::fun => fun.bind(obj)
 
資料來源:


免責聲明!

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



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