天天看點

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

網上關于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