Babel快速入門

首先,做爲入門的話,Babel的用戶手冊是個很不錯的選擇,裏面基本覆蓋了Babel使用的各方面。因此下面主要是我學習Babel的一些筆記,姑且看成是一篇入門吧。javascript

Babel是什麼

按照Babel官網的說法,Babel是一個Javascript編譯器。它能夠把用最新標準編寫的Javascript代碼編譯成如今的瀏覽器或者node環境下能運行的代碼,這個過程叫作「源碼到源碼」編譯,又稱轉譯(transpiling)。經過這個方式,咱們就能夠提早使用下一代的標準和特性進行編碼,而後在如今的環境下運行。html

安裝Babel

一般咱們使用Babel的babel-cli工具在命令行下進行文件的編譯。咱們能夠對babel-cli進行全局安裝,也能夠把它安裝到項目裏。這裏我選擇了把它安裝到項目裏。這樣作的好處是:java

  • 不一樣的項目可能會使用不一樣版本的Babel,使用全局的話只能使用一致的版本node

  • 方便項目的部署,使用全局安裝的話意味着對環境有個隱式的依賴。webpack

除了babel-cli,還有其餘使用Babel的方式,具體能夠看用戶手冊。git

下面咱們開始安裝babel-cli。首先新建一個工做目錄,並建立package.json文件:es6

$ npm init -y

安裝babel-cligithub

$ npm install --save-dev babel-cli

安裝完咱們能夠這樣運行:web

$ ./node_modules/babel-cli/bin/babel.js -V
6.11.4 (babel-core 6.11.4)

可是這樣運行很不方便,咱們能夠經過npm scripts來運行Babel。在package.json文件裏,咱們增長scripts字段,並添加一個腳本:npm

{
  "scripts": {
    "build": "babel src -d lib"
  },
  "devDependencies": {
    "babel-cli": "^6.11.4"
  }
}

這裏增長了一條名字爲build的腳本,命令的內容是把src裏的文件經過Babel轉譯到lib目錄裏。而後咱們能夠經過如下命令運行腳本:

$ npm run build

固然,如今運行這個命令會報錯,由於咱們並無src文件夾。下面咱們正式進入正題。

Babel的基礎使用

轉譯初探

首先咱們建立src目錄,而後建立一個js文件index.js

[1,2,3].map(n => n + 1);

而後運行npm run build命令,就會看到lib文件夾裏多了一個轉譯後的文件index.js。可是打開來看會發現這個轉譯後的文件跟源文件並無區別。由於Babel須要你經過插件(Plugin)或者預設(presets)告訴它作什麼。例如咱們能夠經過babel-preset-es2015告訴Babel把ES2015的文件轉譯成ES5。這也是Babel最經常使用的一個用法之一。

配置文件

要使用插件或者預設(至關於一組插件),咱們須要在Bable的配置文件裏面進行配置。有兩個方式進行配置。

第一個方式是經過.babelrc文件:

{
  "presets": [],
  "plugins": []
}

第二個方式是使用package.json文件:

{
  "name": "my-package",
  "version": "1.0.0",
  "babel": {
    "presets": [],
    "plugins": []
  }
}

使用預設

上面說過,預設就是一組插件的集合,例如預設babel-preset-es2015就是把一堆跟ES2015有關的插件組合起來提供編譯ES2015代碼爲ES5代碼的功能。下面咱們開始使用babel-preset-es2015預設來把ES2015轉譯成ES5。

首先咱們安裝這個預設:

$ npm install --save-dev babel-preset-es2015

而後在配置文件裏添加這個預設:

{
  "presets": [
    "es2015"
  ],
  "plugins": []
}

最後咱們再次運行一次npm run build命令,再次打開lib/index.js文件,咱們會看到代碼已經被編譯成ES5的語法:

"use strict";

[1, 2, 3].map(function (n) {
  return n + 1;
});

Babel的執行

Polyfill

像上面那段轉譯後的代碼咱們能夠直接使用在當前的環境下,可是並非全部轉譯後的文件咱們都只能直接使用,由於雖然Babel能夠編譯目前幾乎全部的ES2015語法,可是一些新的API可能在當前的Javascript環境下沒法支持。例以下面的代碼(假設文件爲lib/index.js):

function addAll() {
  return Array.from(arguments).reduce((a, b) => a + b);
}

轉譯後會變成:

function addAll() {
  return Array.from(arguments).reduce(function(a, b) {
    return a + b;
  });
}

能夠看到語法上已經轉譯成ES5了,可是並非全部的Javascript環境都支持Array.from,例如咱們在IE上運行以下頁面:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
    </head>
    <body>
        <script src="lib/index.js"></script>
        <script>
            console.log(addAll(1, 2, 3, 4, 5));
        </script>
    </body>
</html>

可能會報如下的錯誤:

對象不支持「from」屬性或方法

Babel的解決方法就是使用Polyfill技術(使用了core-jsregenerator),經過在當前的運行環境模擬不存在的API來達到使用新API的目的。

首先咱們安裝babel-polyfill

$ npm install --save babel-polyfill

注意這裏使用的是--save而不是--save-dev,由於咱們須要在代碼裏引入babel-polyfill。咱們須要在文件頂部導入它:

import "babel-polyfill";

在添加這句代碼後,上面的代碼在轉譯後會變成下面這個樣子:

"use strict";

require("babel-polyfill");

function addAll() {
  return Array.from(arguments).reduce(function (a, b) {
    return a + b;
  });
}

由於Babel編譯時默認使用的是CommonJS的模塊規範,因此會看到轉譯後的代碼使用了require方法來加載babel-polyfill。這個在node環境下運行沒有問題,可是在瀏覽器環境下運行就會報錯,由於瀏覽器目前還不原生的支持模塊的加載。那在瀏覽器下怎麼使用babel-polyfill呢?

咱們能夠把babel-polyfill經過外部js的方式加載進來,而不是在js代碼裏進行引入:

<script src="node_modules/babel-polyfill/dist/polyfill.min.js"></script>
<script src="lib/index.js"></script>

可是若是你打算在項目裏使用模塊,上面明顯不是很好的解決方案。下面咱們看看若是解決在瀏覽器環境下模塊的加載問題。

使用模塊

要在瀏覽器環境下加載依賴模塊,有不少方式,例如使用webpack或者browserify之類的打包工具(建議的方式,可是這裏咱們先不涉及)。或者咱們可使用瀏覽器端的模塊加載器進行加載,例如咱們使用AMD模塊規範進行編譯,而後用RequireJS進行加載。下面我使用SystemJS來作例子。

首先咱們安裝es2015-modules-systemjs插件:

$ npm install babel-plugin-transform-es2015-modules-systemjs

而後修改配置文件,在plugins裏添加插件:

{
  "plugins": ["transform-es2015-modules-systemjs"]
}

咱們修改下lib/index.js,把addAll方法導出爲模塊的方法:

import "babel-polyfill";

export function addAll() {
  return Array.from(arguments).reduce((a, b) => a + b);
}

再次對文件進行編譯,編譯後的lib/index.js變成這樣:

"use strict";

System.register(["babel-polyfill"], function (_export, _context) {
  "use strict";

  return {
    setters: [function (_babelPolyfill) {}],
    execute: function () {
      function addAll() {
        return Array.from(arguments).reduce(function (a, b) {
          return a + b;
        });
      }

      _export("addAll", addAll);
    }
  };
});

而後咱們須要在HTML裏引入system.js。因爲SystemJS依賴於Promise,它會加載目錄下system-polyfills.js文件,因此咱們須要確保這個文件的存在。在加載system.js後,咱們就可使用SystemJS進行模塊的加載了:

<html>
    <head>
        <meta charset="utf-8">
    </head>
    <body>
        <script src="system.js"></script>
        <script>
            System.config({
                baseURL: './lib',
                map: {
                    'babel-polyfill': './node_modules/babel-polyfill/dist/polyfill.min.js'
                }
            });

            System.import('index.js').then(function(m) {
                console.log(m.addAll(1, 2, 3, 4, 5)); // 15
            });
        </script>
    </body>
</html>

出於性能的考慮,也能夠用像Bluebirdes6-promise這樣的polyfill作替代,在system.js以前加載。

後記

自此,咱們學習到了Babel的一些基礎用法,包括安裝和運行,以及配置和預設的用法,同時也初探了一些編譯後的文件的運行問題。可是要用好Babel,還有不少問題須要繼續探討,期待個人下一篇筆記。

參考

https://babeljs.io/
https://github.com/thejamesky...
https://github.com/systemjs/s...

相關文章
相關標籤/搜索