1. 程式人生 > 實用技巧 >babel 的介紹及其配置

babel 的介紹及其配置

vue/cli -- babel

Babel 是一個工具鏈,主要用於將 ECMAScript 2015+ 版本的程式碼轉換為向後相容的 JavaScript 語法,以便能夠執行在當前和舊版本的瀏覽器或其他環境中。

1. babel的作用

  1. 語法轉換
  2. 通過 Polyfill 方式在目標環境中新增缺失的特性
  3. 原始碼轉換 (codemods)

為什麼要用babel轉換程式碼呢:

@babel/polyfill

例:如果我們要使用Array.prototype.find(),但是某個版本的瀏覽器不支援此方法,我們可以通過babel引入相關的Polyfill檔案就可以了

注:Polyfill 是一塊程式碼(通常是 Web 上的 JavaScript),用來為舊瀏覽器提供它沒有原生支援的較新的功能。

@babel/preset-env

例:

1//箭頭函式
2letFn=()=>{
3//
4}

因為一些瀏覽器根本就不識別這些程式碼,這時候就需要把這些程式碼轉換成瀏覽器識別的程式碼。 babel就是做這個事情的。

2. babel的工作原理

Code => AST => new AST => new Code

為了轉換我們的程式碼, babel做了三件事:

  • Parser:解析我們的程式碼轉換為 AST。(@babel/parser)
  • Transformer:利用我們配置好的 plugins/presets把 Parser生成的 AST轉變為新的 AST。(@babel/preset-*)
  • Generator:把轉換後的 AST生成新的程式碼(@babel/generator)

從圖上看 Transformer佔了很大一塊比重,這個轉換過程就是 babel中最複雜的部分,我們平時配置的 plugins/presets就是在這個模組起作用。

*注:抽象語法樹(AST)Abstract Syntax Tree是javascript的最底層結構,babel通過操作AST實現對原始碼的修改,可以通過recast外掛檢視AST的結構

3. babel的使用

  • 正常我們需要安裝以下依賴
1npminstall--save-dev@babel/core@babel/cli@babel/preset-env
2
npminstall--save@babel/polyfill
  • 建立一個名為config的配置檔案
 1module.exports={
2presets:[
3[
4require('@babel/preset-env'),
5{
6targets:{
7edge:"17",
8firefox:"60",
9chrome:"67",
10safari:"11.1",
11},
12useBuiltIns:'usage'
13},
14],
15],
16//上面的瀏覽器列表只是一個任意示例。您將不得不對其進行調整以適合您要支援的瀏覽器。
17plugins:[
18//
19]
20}
  • 執行此命令,將src目錄中的所有程式碼編譯為lib
1./node_modules/.bin/babelsrc--out-dirlib

@babel/cli

Babel帶有內建CLI,可用於從命令列編譯檔案。

@babel/core

@babel/core 包括了整個babel工作流,也就是說在@babel/core裡面我們會使用到@babel/parsertransformer[s]、以及@babel/generator

所有的transformations都會使用babel.config.js檔案

@babel/parser

@babel/parser的作用是將原始碼解析成 AST ,方便各個外掛分析語法進行相應的處理。

@babel/generator

@babel/generator將修正後的AST解碼生成js程式碼。

@babel/preset-env

@babel/preset-env是一個智慧預設,可讓您使用最新的JavaScript,轉化最新語法如箭頭函式, class, 擴充套件運算子,想要轉換最新的api還需引入@babel/polyfill

@babel/preset-env接受您指定的任何目標環境,並根據其對映檢查它們,以編譯外掛列表,並將其傳遞給Babel。

預設情況下,除非設定了target或ignoreBrowserslistConfig選項,@babel/preset-env將使用browserslist配置源

browserslist配置源從以下位置讀取:

  1. package.json檔案中的browserslist欄位
  2. .browserslistrc配置檔案
  3. browserslist.config.js 配置檔案
  4. 執行環境變數BROWSERSLIST
  5. 預設如下
1"browserslist":[
2"defaults"
3]
4//defaults=>>0.5%,last2versions,FirefoxESR,notdead

useBuiltIns:

  • 此選項配置如何@babel/preset-env處理polyfill
  • 'usage':支援按需引入,優化了core-js匯入

@babel/polyfill

babel只負責語法轉換,比如將ES6的語法轉換成ES5。但如果有些物件、方法,瀏覽器本身不支援,比如:

  1. 全域性物件:Promise、WeakMap 等。
  2. 全域性靜態函式:Array.from、Object.assign 等。
  3. 例項方法:比如 Array.prototype.includes 等。

此時,需要引入@babel/polyfill來模擬實現這些物件、方法。需要安裝在生產依賴中

3. @vue/cli中的babel

我們從package.json入手

 1"dependencies":{
2"axios":"^0.19.1",
3"core-js":"^3.4.4",
4"vue":"^2.6.10",
5"vue-meta":"^2.3.2",
6"vue-router":"^3.1.3",
7"vuex":"^3.1.2"
8},
9"devDependencies":{
10"@vue/cli-plugin-babel":"^4.1.0",
11"@vue/cli-plugin-eslint":"^4.1.0",
12"@vue/cli-plugin-unit-jest":"^4.1.0",
13"@vue/cli-service":"^4.1.0",
14"@vue/eslint-config-standard":"^4.0.0",
15"@vue/test-utils":"1.0.0-beta.29",
16"babel-eslint":"^10.0.3",
17"babel-plugin-import":"^1.13.0",
18"eslint":"^5.16.0",
19"eslint-plugin-vue":"^5.0.0",
20"image-webpack-loader":"^6.0.0",
21}

core-js

由於自@babel/polyfill7.4.0起已棄用,可以直接新增core-js和設定版本。在@vue/cli專案中,只安裝了core-js

core-js是我們能夠使用新的API的最重要的包,然而一般情況它隱藏在webpack編譯後的程式碼中,我們一般不會去檢視

  • 它是JavaScript標準庫的polyfill
    • 最新的 ECMAScript 標準
    • ECMAScript 標準庫提案
    • 一些 WHATGW / W3C 標準(跨平臺或者 ECMAScript 相關)
  • 它儘可能的進行模組化,讓你能選擇你需要的功能
  • 它可以不汙染全域性空間
  • 它和babel高度整合,可以對core-js的引入進行最大程度的優化

@vue/cli-plugin-babel

這就是vue-cli特有的babel外掛,其中包括babel7,babel-loader,@vue/babel-preset-app

其中也載入了@babel/core工作流,檢視./node_modules/@vue/babel-preset-app,其中配置了:

1presets:[
2[require('@babel/preset-env'),{
3useBuiltIns,
4corejs:3
5}]
6]

babel-loader則是webpack配置的前處理器

babel-plugin-import

babel-plugin-import是一款 babel 外掛,它會在編譯過程中將 import 的寫法自動轉換為按需引入的方式
例:vant

1plugins:[
2['import',{
3libraryName:'vant',
4libraryDirectory:'es',
5style:true
6},'vant']
7]

babel-eslint

ESLint 預設使用Espree作為其解析器,你可以在配置檔案中指定一個不同的解析器

ESLint不支援Babel支援的某些語法節點。使用babel-eslint時,將對ESLint進行修補,並將您的程式碼轉換為ESLint可以理解的程式碼。相關配置

.eslintrc.js中:

1parserOptions:{
2parser:'babel-eslint'
3}