搞懂babel7常用的配置和優化,這篇就夠了!

晨曦時夢見兮發表於2019-03-15

網上關於babel7的文章很多,但是大多都沒有實踐,很多講的模稜兩可。 本文將手把手的帶你看各種配置下的輸入輸出轉換,徹底讓你瞭解babel7到底該怎麼去配置和優化。

首先我們知道進入了babel7的時代,stage-0這種已經作為不推薦使用的present了,最流行的應該是@babel/present-env 顧名思義讓babel擁有根據你的環境來編譯不同程式碼的需求。

targets

我們先配置最基礎的.babelrc配置

{
  "presets": [
    [
      "@babel/preset-env",
      {
        "targets": {
          "chrome": "58",
          "ie": "10"
        }
      },
    ]
  ],
}
複製程式碼

targets配置的意思就是讓babel根據你寫入的相容平臺來做程式碼轉換,這裡我們指定ie10為我們要相容的最低版本,來看下面es6程式碼的輸出。

輸入: src/main.js

const a = () => {}
複製程式碼

輸出: dist/main.js

var a = function a() {};
複製程式碼

這裡因為ie10是不支援es6語法的,所以程式碼被全部轉換,如果我們把ie10這條去掉,因為高版本的chrome是支援es6大部分語法的,所以程式碼就不會被做任何轉換了。

browserlist 這裡是具體的可配置列表,可以根據你自己專案的相容性要求來配置。

useBuiltIns

首先我們來看一行簡單的程式碼

a.includes(1);
複製程式碼

includes作為陣列的例項方法,在某些瀏覽器其實是不支援的,babel預設的轉換對於這種場景並不會做處理,同樣不會處理的包括WeakMap, WeakSet, Promise等es6新引入的類,所以我們需要babel-polyfill為我們這些例項方法等等打上補丁。

在很多專案中我們會看到專案的main.js入口頂部require了babel-polyfill包, 或者指定webpack的entry為陣列,第一項引入babel-polyfill包,這樣的確沒問題而且很保險,但是很多場景下我們可能只是使用了少量需要polyfill的api,這個時候全量引入這個包就顯得很不划算,babel給我們提供了很好的解決方案,那就是useBuiltIns 這個配置,下面來看例項。

{
  "presets": [
    [
      "@babel/preset-env",
      {
        "useBuiltIns": "usage",
        "targets": {
          "chrome": "58",
          "ie": "10"
        }
      },
    ]
  ],
}
複製程式碼

輸入: src/main.js

a.includes(1)
Promise.reject()
複製程式碼

輸出: dist/main.js

require("core-js/modules/es6.promise");

require("core-js/modules/es7.array.includes");

require("core-js/modules/es6.string.includes");

a.includes(1);
Promise.reject();
複製程式碼

babel幫我們做好了程式碼分析,在需要用到polyfill的地方再幫你引入這個單獨的補丁,這樣就實現了按需引入~

@babel/plugin-transform-runtime

這個外掛是幫我們把一些babel的輔助方法由直接寫入程式碼專為按需引入模組的方式引用, 我們先來看不使用這個外掛時候,我們對於es6 class的轉換。

輸入: src/main.js

class A {}
複製程式碼

輸出: dist/main.js

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

var A = function A() {
  _classCallCheck(this, A);
};
複製程式碼

看似沒問題,轉換的很好,但是如果在很多模組都用了class語法的情況下呢?輔助函式_classCallCheck就會被重複寫入多次,佔用無意義的空間。 解決方法就是引入@babel/plugin-transform-runtime .babelrc

{
  "presets": [
    [
      "@babel/preset-env",
      {
        "useBuiltIns": "usage",
        "targets": {
          "chrome": "58",
          "ie": "10"
        }
      },
    ]
  ],
  "plugins": [
    "@babel/plugin-transform-runtime",
  ]
}
複製程式碼

輸入: src/main.js

class A {}
複製程式碼

輸出: dist/main.js

var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));

var A = function A() {
  (0, _classCallCheck2.default)(this, A);
};
複製程式碼

這樣就解決了輔助函式重複寫入的問題了。

總結

babel7的版本下,利用present-env做按需轉換,利用useBuiltIn做babel-polyfill的按需引入,利用transform-runtime做babel輔助函式的按需引入。

原文連結

歡迎star

相關文章