babel7實踐

前些天使用了 babel7,特來作個筆記。原文發佈在GitHubjavascript

presets

babel7 中,已經廢棄了以前的階段性提案,如今統一使用 @babel/preset-env。因此呢,這裏卻是省去了一些麻煩。在 webpack 配置中 preset-env 配合 babel-loader 就能夠轉換 ES2015+ 語法了。同時,官方建議咱們使用 targets 設定目標瀏覽器決定須要兼容的功能。舉個例子:java

module.exports = {
  presets: [
    [
      '@babel/preset-env',
      {
        targets: {
          ie: "11"
        }
      }
    ]
  ]
}

polyfill

polyfill 在以前都是用來引入新的 api 和功能的。如咱們經常使用的 promiseObject.assign 等。在 babel6 及以前,只須要在入口引入 polyfill 便可。然而這也帶來了問題,一次性加載了整個 polyfill,十分冗餘。 而用了 babel7 經過簡單的配置就能夠達成按需加載的目的,咱們也再也不須要手動引入 polyfillnode

useBuiltIns

沒錯,使用這個新的配置項,就能夠實現按需加載 polyfill。其值可取如下3個:webpack

false

值爲 false 的時候,至關於沒用,這時就得手動引入全部的 polyfillgit

entry

使用 entry 的時候,也須要手動引入 polyfill,即 import '@babel/polyfill';,同時也引入了全部的 polyfill。這個配置項,總以爲沒什麼用,若是有老哥知道的話能夠在評論區提出一塊兒討論。github

usage

值爲 usage 的時候,無需引入 polyfillbabel 會自動按需加載須要的功能:web

{
  \\...
  useBuiltIns: 'usage'
}

若是須要在命令行打印加載項,能夠設置 debugnpm

{
  \\...
  useBuiltIns: 'usage',
  dubug: true
}

plugin-transform-runtime

例如使用 class(類) 的時候,babel 會在這前面添加一個幫助函數。以下所示:
源代碼:api

// source code
class Test {}

編譯後:promise

"use strict";

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

var Test = function Test() {
  _classCallCheck(this, Test);
};

能夠看到,在編譯輸出的代碼裏,helper 函數被直接嵌入代碼中。若是你只有這一個 js 文件用到了這個 helper,那這樣並無問題。但試想一下,若是你有不少個腳本文件,每個你都用到了 classbabel 可無論你這麼多,每一個編譯後的文件都包含一個如出一轍的 helper 函數,便形成了冗餘。所幸,咱們可使用 @babel/plugin-transform-runtime@babel/runtime 來解決這個問題。添加以下配置:

plugins: [
  '@babel/plugin-transform-runtime'
]

此時再編譯上面的代碼,獲得的結果以下:

"use strict";

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

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

var Test = function Test() {
  (0, _classCallCheck2.default)(this, Test);
};

此時再也不是直接把 helper 函數嵌入代碼中,而是使用 require 加載公共 helper

使用 polyfill 仍是 runtime

  • 對於要發佈給別人使用的工具和庫來講,使用 @babel/runtime 比較合適。由於 @babel/polyfill 會污染全局環境,別人引入你的庫可能會形成沒必要要的污染。
  • @babel/runtime 不能提供一些實例方法,諸如 "foobar".includes("foo") 這類的。還需本身手動引入。

對於本身的應用項目,仍是引入 @babel/polyfill 更好,提供的功能更全面,也不須要擔憂全局污染。但如我上面所說的,一些 helper 函數,若是不使用 @babel/plugin-transform-runtime 插件的話,會引入冗餘的代碼。而這二者放在一塊兒使用的時候,若是沒有對 plugin-transform-runtime 進行配置,是不會有重複功能的引入的。

總結

上面說了這麼多,如今給出 babel7webpack 的實踐做爲結束。
1.添加依賴

cnpm i --save-dev babel-loader @babel/core @babel/preset-env @babel/plugin-transform-runtime
// &
cnpm i --save @babel/polyfill @babel/runtime

2.webpack 配置

module.exports = {
  // ...
  module: {
    rules: [
      {
        test: /\.js$/,
        loader: 'babel-loader',
        exclude: /node_modules/
      }
    ]
  }
};

3.babel 配置
如下是在本身的應用項目中的配置:

// babel.config.js
module.exports = {
  presets: [
    [
      '@babel/preset-env',
      {
        useBuiltIns: 'usage',
        targets: {
          ie: 10 // 根據本身的目標環境進行配置
        },
        debug: true,
        // corejs這一項也須要加上,corejs有2和3兩個版本
        // 若是不肯定有沒有下載core-js,可執行 cnpm i core-js@2 --save
        corejs: 2
      }
    ]
  ],
  plugins: [
    '@babel/plugin-transform-runtime'
  ]
};

發佈給別人使用的工具或庫,可使用如下配置:

// babel.config.js
module.exports = {
  presets: [
    '@babel/preset-env'
  ],
  plugins: [
    [
      '@babel/plugin-transform-runtime',
      {
        corejs: 2
        // ...
      }
    ]
  ]
};
相關文章
相關標籤/搜索