Babel 快速入門

簡介

Babel 是一個 JavaScript 編譯器,可將咱們代碼中的 ES6 語法轉換爲 ES5 的語法,使咱們的代碼能在不支持 ES6 語法的環境中正常運行。配合一些插件,咱們甚至能直接使用 ES6 標準的一些新特性,而無需等待各大瀏覽器的實現,也無需擔心兼容性。css

快速體驗

1. 安裝依賴

新建 babel_test 文件夾,在命令行裏進入該文件夾,並執行以下命令:html

npm init -y # 生成 package.json 文件
npm i -D babel-cli babel-preset-env
npm i -S babel-polyfill
  • babel-cli 是 Babel 內置的一個 CLI,可經過命令行操做來編譯文件。這是一個可選的開發依賴包,在實際開發中可根據需求決定是否安裝。
  • babel-preset-env 會根據咱們配置的環境自動將該環境不支持的語法轉換 ES5 的語法。
  • babel-polyfill 是一個相對完整的 ES6 環境,能夠爲代碼的運行環境補充缺乏的 API。這是一個可選的依賴包,但我的建議最好安裝並引入到代碼中,詳解見下文。
在編寫本文章時,上面依賴包的最新版本分別爲 babel-cli 6.26.0、babel-preset-env 1.6.一、babel-polyfill 6.26.0,若是安裝的版本不一致,可能會獲得不同的結果。

2. 配置 Babel

新建 .bablerc 文件,內容以下:node

{
    "presets": ["env"]
}

.bablerc 是 Babel 的默認配置文件,運行 Babel 時會自動讀取該文件的配置。上面 .bablerc 文件配置的意思是對代碼進行徹底的轉換。git

3. 編寫代碼

新建 source.js 文件,內容以下:es6

// 這裏的代碼無任何意義,只用做示例
const sayHi = () => {
    const str = 'Hello World!';
    const arr = [...str];

    alert(arr.join(''));
};
... 是 ES6 語法,詳情可參考 http://es6.ruanyifeng.com/#docs/array

4. 編譯

執行如下命令就能夠把 source.js 的代碼轉換爲 ES5 的語法,並把結果輸出到 target.jsgithub

./node_modules/babel-cli/bin/babel.js source.js -o target.js
babel-cli 的詳細命令可參考 https://babeljs.cn/docs/usage/cli/

target.js 的內容最終以下:web

'use strict';

function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }

var sayHi = function sayHi() {
    var str = 'Hello World!';
    var arr = [].concat(_toConsumableArray(str));

    alert(arr.join(''));
};

能夠看到 Babel 在 target.js 添加了 _toConsumableArray 函數,並將 [...str] 替換成了 [].concat(_toConsumableArray(str)) 。到這裏咱們已經成功的將代碼中的 ES6 語法轉換爲 ES5 語法,Babel 的使用就是這麼簡單。chrome

babel-polyfill

若是咱們仔細查看上文中的 target.js ,會發現 Babel 添加的 _toConsumableArray 函數居然使用了 ES6 的特性 Array.from ,也就是說咱們使用 Babel 轉換後代碼裏可能還會存在 ES6 的東西!這個問題能夠參考 https://www.zhihu.com/question/49382420npm

這裏咱們須要重點注意的是:json

Babel 默認只轉換新的 JavaScript 句法(syntax),而不轉換新的 API,好比Iterator、Generator、Set、Maps、Proxy、Reflect、Symbol、Promise等全局對象,以及一些定義在全局對象上的方法(好比Object.assign)都不會轉碼。—— 《ECMAScript 6入門》

爲了確保轉換後的代碼能正常的運行,最好在代碼以前引入 babel-polyfill(這是一個實現了部分 ES6 特性的包)。

<!-- 在 HTML 文件中先引入 babel-polyfill 再引入 target.js -->
<!-- src 屬性裏的 6.26.0 是本文章編寫時 babel-polyfill 的最新穩定版本,你可能須要根據實際引入對應的版本 -->
<script src="https://cdn.bootcss.com/babel-polyfill/6.26.0/polyfill.min.js"></script>
<script src="target.js"></script>

至此,咱們能夠放心的隨意使用 ES6 的特性了。

優化

其實現代瀏覽器或多或少都實現了部分 ES6 標準,如 Chrome v64 甚至已實現了 97% 的功能。若是咱們肯定咱們的代碼只運行在 Chrome v64 ,那麼像 source.js 中的箭頭函數則無需轉換,由於 Chrome v64 已經支持這樣的語法了。同理咱們也無需引入整個 babel-polyfill ,只需引入其中 Chrome v64 不支持的部分便可。

Babel 的強大之處在這裏更能獲得體現。當咱們配置了代碼的運行環境以後,Babel 會自動判斷該環境對 ES6 的實現程度,而後只把源代碼中該環境不支持的語法進行轉換。若是咱們在源代碼中利用模塊化的方式引入 babel-polyfill ,Babel 也會對其進行優化,只引入該環境還沒有實現的模塊。下面就讓咱們來體現一下這強大的功能。

修改配置文件 .babelrc ,內容以下:

{
    "presets": [
        [
            "env",
            {
                "targets": { // 配置代碼的運行環境
                    "chrome": 64
                },
                "useBuiltIns": true // 開啓對 babel-polyfill 的優化
            }
        ]
    ]
}

修改source.js,內容以下:

// 使用 ES6 的模塊化標準引入 babel-polyfill
import 'babel-polyfill';

const sayHi = () => {
    const str = 'Hello World!';
    const arr = [...str];

    alert(arr.join(''));
};

運行命令編譯成功後,target.js 的內容以下:

'use strict';

require('core-js/modules/web.timers');

require('core-js/modules/web.immediate');

require('core-js/modules/web.dom.iterable');

const sayHi = () => {
    const str = 'Hello World!';
    const arr = [...str];

    alert(arr.join(''));
};

能夠看到,箭頭函數和 ...str 都沒有變化,由於 Chrome v64 已經支持這樣的語法。import 'babel-polyfill' 則變成了用 CommonJS 的方式引入了三個小模塊,這是 Babel 經過查詢 compat-table 得知 Chrome v64 還沒有實現的特性後添加的模塊。

以上即是 Babel 的一些基本使用了。

最後說明一下:

  • 模塊化並非 Babel 的工做,Babel 僅負責轉換語法。Babel 輸出的 target.js 使用了 CommonJS 的模塊化規範,這還須要一些構建工具對其進一步編譯才能在 Chrome v64 上運行。
  • core-js 是真正實現了 ES6 特性的包,是 babel-polyfill 的依賴,babel-polyfill 對其進行了一些包裝。

參考

相關文章
相關標籤/搜索