成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

Babel 7使用總結(jié)

seasonley / 3503人閱讀

摘要:使用總結(jié)本文基于??梢砸爰儍舭娴呐渲庙椫械膶傩钥梢苑奖愕氖褂?。例如使用時,需要先安裝配置文件為得到的結(jié)果是可以看到引入時得到了一個別名,可以避免全局變量污染,但是可以發(fā)現(xiàn)實例方法并沒有得到相應(yīng)的處理。

Babel 7使用總結(jié)

? 2019-07-08

本文基于Babel 7.4.5。


? Babel主要模塊如上圖所示,接下來將分別介紹。

1. @babel/core

@babel/core主要是進(jìn)行代碼轉(zhuǎn)換的一些方法,可以將源代碼根據(jù)配置轉(zhuǎn)換成兼容目標(biāo)環(huán)境的代碼。

import * as babel from "@babel/core";
babel.transform("code();", options, function(err, result) {
  result.code;
  result.map;
  result.ast;
});
2. @babel/cli

@babel/cli是 babel 提供的命令行工具,用于命令行下編譯源代碼。

首先安裝依賴:

npm install --save-dev @babel/core @babel/cli

新建一個js文件:

let array = [1,2,3,4,5,6];
array.includes(function(item){
    return item>2;
})
class Robot {
    constructor (msg) {
        this.message = msg
    }
    say () {
        alertMe(this.message)
    }
}
Object.assign({},{
    a:1,b:2
})
const fn = () => 1;
new Promise();

執(zhí)行轉(zhuǎn)換:

npx babel index.js --out-file out.js

可以發(fā)現(xiàn)輸出代碼沒有變化,這是因為沒有進(jìn)行配置來確定怎么進(jìn)行轉(zhuǎn)換。

3. @babel/plugin*

babel是通過插件來進(jìn)行代碼轉(zhuǎn)換的,例如箭頭函數(shù)使用plugin-transform-arrow-functions插件來進(jìn)行轉(zhuǎn)換。

首先安裝該插件:

npm install --save-dev @babel/plugin-transform-arrow-functions

可以通過@babel/cli傳參或者配置文件的方式使用插件:

@babel/cli

npx babel index.js --out-file out.js --plugins=@babel/plugin-transform-arrow-functions

則可以得到out.js文件,可以看到箭頭函數(shù)已經(jīng)被轉(zhuǎn)換。

let array = [1, 2, 3, 4, 5, 6];
array.includes(function (item) {
  return item > 2;
});
class Robot {
    constructor (msg) {
        this.message = msg
    }
    say () {
        alertMe(this.message)
    }
}
Object.assign({}, {
  a: 1,
  b: 2
});
const fn = function () {
  return 1;
};

new Promise();

配置文件babel.config.js(javascript寫法)或.babelrc(json寫法),使用配置文件是更加常用的方式。

module.exports = function (api) {
    api.cache(true);

    const plugins = [ "@babel/plugin-transform-arrow-functions" ];

    return {
        plugins
    };
}

4. @babel/presets

我們在index.js中使用了多種es6的語法,一個個的導(dǎo)入插件很麻煩,presets是一組預(yù)設(shè)好的插件集合。官方為常見環(huán)境組裝了一些 presets (當(dāng)然也可以自己配置):

@babel/preset-env

@babel/preset-flow

@babel/preset-react

@babel/preset-typescript

我們使用@babel/preset-env為例(使用前需npm install @babel/preset-env):

module.exports = function (api) {
    api.cache(true);
    const presets =  [
        ["@babel/preset-env"]
    ];
    return {
        presets
    };
}

得到的結(jié)果如下, 可以看到箭頭函數(shù)被編譯、es6類、let聲明被編譯了。

"use strict";

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

function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }

function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }

var array = [1, 2, 3, 4, 5, 6];
array.includes(function (item) {
  return item > 2;
});

var Robot =
/*#__PURE__*/
function () {
  function Robot(msg) {
    _classCallCheck(this, Robot);

    this.message = msg;
  }

  _createClass(Robot, [{
    key: "say",
    value: function say() {
      alertMe(this.message);
    }
  }]);

  return Robot;
}();

Object.assign({}, {
  a: 1,
  b: 2
});

var fn = function fn() {
  return 1;
};

new Promise();

但是可以看到數(shù)組的實例方法includes、對象的靜態(tài)方法,以及promise并沒有被編譯。

這是因為babel 把 Javascript 語法為syntax 和 api, api 指那些我們可以通過 函數(shù)重新覆蓋的語法 ,類似 includes, map, includes, Promise, 凡是我們能想到重寫的都可以歸屬到api。syntax 指像箭頭函數(shù),let,const,class, 依賴注入 Decorators等等這些,我們在 Javascript在運行是無法重寫的,想象下,在不支持的瀏覽器里不管怎么樣,你都用不了 let 這個關(guān)鍵字。

@babel/presets默認(rèn)只對syntax進(jìn)行轉(zhuǎn)換,我們需要使用@babel/polyfill來提供對api的的支持。

5. @babel/polyfill

@babel/polyfill由core-js2和regenerator-runtime組成,后者是facebook開源庫,用來實現(xiàn)對generator、async函數(shù)等的支持,前者是js標(biāo)準(zhǔn)庫,包含不同版本javascipt語法的實現(xiàn)。

只要在js文件的入口頂部引入@babel/polyfill就可以在后問的代碼中自由的使用es6 api了。

但是整體@babel/polyfill整個包體積較大,我們通常只使用了其中一部分方法,而引入整個庫顯然是不合適的。所以你可以只引入使用的方法:

import "core-js/features/array/from"; // <- at the top of your entry point
import "core-js/features/array/flat"; // <- at the top of your entry point
import "core-js/features/set";        // <- at the top of your entry point
import "core-js/features/promise";    // <- at the top of your entry point

Array.from(new Set([1, 2, 3, 2, 1]));          // => [1, 2, 3]
[1, [2, 3], [4, [5]]].flat(2);                 // => [1, 2, 3, 4, 5]
Promise.resolve(32).then(x => console.log(x)); // => 32

如果你不想污染全局命名空間(例如在寫一個npm庫時,要保持其隔離性)??梢砸爰儍舭妫?/p>

import from from "core-js-pure/features/array/from";
import flat from "core-js-pure/features/array/flat";
import Set from "core-js-pure/features/set";
import Promise from "core-js-pure/features/promise";

from(new Set([1, 2, 3, 2, 1]));                // => [1, 2, 3]
flat([1, [2, 3], [4, [5]]], 2);                // => [1, 2, 3, 4, 5]
Promise.resolve(32).then(x => console.log(x)); // => 32

preset-env的配置項中的useBuiltIns屬性可以方便@babel/polyfill的使用。

useBuiltIns:false(default):此時不對 polyfill 做操作。如果引入 @babel/polyfill,則無視配置的瀏覽器兼容,引入所有的 polyfill

useBuiltIns:"entry":根據(jù)配置的瀏覽器兼容,引入瀏覽器不兼容的 polyfill。需要在入口文件手動添加 import "@babel/polyfill",會自動根據(jù) browserslist 替換成瀏覽器不兼容的所有 polyfill。

useBuiltIns:"usage":不需要在文件頂部手動引入@babel/polyfill,會根據(jù)代碼中的使用進(jìn)行按需添加。

在這里使用useBuiltIns:"usage"作為示例,babel.config.js文件如下:

module.exports = function (api) {
    api.cache(true);

    const presets =  [
        ["@babel/preset-env",
            {
            "useBuiltIns": "usage",
            "targets":{
                "browsers":["> 1%", "last 2 versions", "not ie                                                             <= 8"]
                }
            }
        ]
    ];
    return {
        presets,
        // plugins
    };
}

得到的編譯結(jié)果:

"use strict";

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

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

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

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

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

function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }

function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }

var array = [1, 2, 3, 4, 5, 6];
array.includes(function (item) {
  return item > 2;
});

var Robot =
/*#__PURE__*/
function () {
  function Robot(msg) {
    _classCallCheck(this, Robot);

    this.message = msg;
  }

  _createClass(Robot, [{
    key: "say",
    value: function say() {
      alertMe(this.message);
    }
  }]);

  return Robot;
}();

Object.assign({}, {
  a: 1,
  b: 2
});

var fn = function fn() {
  return 1;
};

new Promise();

可以看到實現(xiàn)了polyfill的按需引入。但是在配置文件中未指定core-js版本時,默認(rèn)會使用core-js2。命令行會出現(xiàn)如下提示:

WARNING: We noticed you"re using the useBuiltIns option without declaring a core-js version. Currently, we assume version 2.x when no version is passed. Since this default version will likely change in future versions of Babel, we recommend explicitly setting the core-js version you are using via the corejs option.

這是因為core-js3已經(jīng)發(fā)布,@babel/polyfill不支持從core-js2到core-js3的平滑過渡,所以在babel 7.4版本中,已經(jīng)廢棄@babel/polyfill(只能用core-js2),而是直接引入core-js3和regenerator-runtime代替。

import "@babel/polyfill";

// migration

import "core-js/stable";
import "regenerator-runtime/runtime";

使用core-js3有很多優(yōu)點,首先就是新,包含很多新特性,其次就是可以配合@babel/runtime(后文詳述)。更多優(yōu)點見core-js@3, babel and a look into the future。

使用core-js3是 babel.config.js如下:

module.exports = function (api) {
    api.cache(true);

    const presets =  [
        ["@babel/preset-env",
            {
            "useBuiltIns": "usage",
            "corejs":3,
            "targets":{
                "browsers":["> 1%", "last 2 versions", "not ie <= 8"]
                }
            }
        ]
    ];
    return {
        presets,
        // plugins
    };
}

仔細(xì)觀察上面的編譯結(jié)果可以發(fā)現(xiàn)有兩個問題。

高階語法向低階語法轉(zhuǎn)化時引入了了很多helper函數(shù)(如_classCallCheck)。當(dāng)文件數(shù)量很多時,每個文件都引入這些helper函數(shù)會使得文件體積增大,怎么這些helper函數(shù)抽離到多帶帶的模塊,然后按需引入呢?

雖然polyfill是按需引入的,但是會污染全局命名空間,當(dāng)你寫的是公共庫時,可能會與使用者本地的方法產(chǎn)生沖突。例如你在你的庫中引入了polyfill中的Promise,使用者自身定義了自己的Promise,這就容易產(chǎn)生沖突。如何將你的公共庫中引入的polyfill api隔離起來呢?

要解決這兩個問題,就要需要使用@babel/runtime和@babel/plugin-transform-runtime了。

6. @babel/runtime

@babel/runtime依賴@babel/helpers和regenerator-runtime,helper函數(shù)都可以從這里面引入,手動的肯定不可能,于是 babel 提供了 @babel/plugin-transform-runtime 來替我們做這些轉(zhuǎn)換。

babel.config.js文件為:

module.exports = function (api) {
    api.cache(true);

    const presets =  [
        ["@babel/preset-env",
            {
            "useBuiltIns": "usage",
            "targets":{
                "browsers":["> 1%", "last 2 versions", "not ie <= 8"]
                }
            }
        ]
    ];
    const plugins = [
        ["@babel/plugin-transform-runtime"]
    ]

    return {
        presets,
        plugins
    };
}

得到的編譯結(jié)果是:

"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
require("core-js/modules/es6.promise");
require("core-js/modules/es6.object.to-string");
require("core-js/modules/es6.object.assign");

var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
require("core-js/modules/es7.array.includes");

var array = [1, 2, 3, 4, 5, 6];
array.includes(function (item) {
  return item > 2;
});
var Robot =
/*#__PURE__*/
function () {
  function Robot(msg) {
    (0, _classCallCheck2.default)(this, Robot);
    this.message = msg;
  }

  (0, _createClass2.default)(Robot, [{
    key: "say",
    value: function say() {
      alertMe(this.message);
    }
  }]);
  return Robot;
}();
Object.assign({}, {
  a: 1,
  b: 2
});
var fn = function fn() {
  return 1;
};
new Promise();

可以看到我們的第一個問題已經(jīng)圓滿解決了。

解決第二個問題需要使用@babel/plugin-transform-runtime option中的corejs參數(shù)。默認(rèn)為false,不對polyfill進(jìn)行處理??梢栽O(shè)為不同版本的core-js。

例如使用core-js2時,需要先安裝

npm install --save @babel/runtime-corejs2

配置文件為:

module.exports = function (api) {
    api.cache(true);

    const presets =  [
        ["@babel/preset-env",
            {
            "useBuiltIns": "usage",
            "targets":{
                "browsers":["> 1%", "last 2 versions", "not ie <= 8"]
                }
            }
        ]
    ];
    const plugins = [
        ["@babel/plugin-transform-runtime",{corejs:2}]
    ]

    return {
        presets,
        plugins
    };
}

得到的結(jié)果是:

"use strict";

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

var _promise = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/promise"));

var _assign = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/object/assign"));

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

var _createClass2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/createClass"));

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

var array = [1, 2, 3, 4, 5, 6];
array.includes(function (item) {
  return item > 2;
});

var Robot =
/*#__PURE__*/
function () {
  function Robot(msg) {
    (0, _classCallCheck2.default)(this, Robot);
    this.message = msg;
  }

  (0, _createClass2.default)(Robot, [{
    key: "say",
    value: function say() {
      alertMe(this.message);
    }
  }]);
  return Robot;
}();

(0, _assign.default)({}, {
  a: 1,
  b: 2
});

var fn = function fn() {
  return 1;
};

new _promise.default();

可以看到polyfill引入時得到了一個別名,可以避免全局變量污染,但是可以發(fā)現(xiàn)實例方法includes并沒有得到相應(yīng)的處理。這是core-js2沒有解決的問題,隨著2019年3月core-js3的發(fā)布,這個問題得到了完美解決。我們將corejs設(shè)為3,得到了結(jié)果如下:

"use strict";

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

var _promise = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/promise"));

var _assign = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/object/assign"));

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

var _createClass2 = _interopRequireDefault(require("@babel/runtime-corejs3/helpers/createClass"));

var _includes = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/instance/includes"));

var array = [1, 2, 3, 4, 5, 6];
(0, _includes.default)(array).call(array, function (item) {
  return item > 2;
});

var Robot =
/*#__PURE__*/
function () {
  function Robot(msg) {
    (0, _classCallCheck2.default)(this, Robot);
    this.message = msg;
  }

  (0, _createClass2.default)(Robot, [{
    key: "say",
    value: function say() {
      alertMe(this.message);
    }
  }]);
  return Robot;
}();

(0, _assign.default)({}, {
  a: 1,
  b: 2
});

var fn = function fn() {
  return 1;
};

new _promise.default();
7. @babel/register

經(jīng)過 babel 的編譯后,我們的源代碼與運行在生產(chǎn)下的代碼是不一樣的。

babel-register 則提供了動態(tài)編譯。換句話說,我們的源代碼能夠真正運行在生產(chǎn)環(huán)境下,不需要 babel 編譯這一環(huán)節(jié)。

我們先在項目下安裝 babel-register:

$ npm install --save-dev @babel/register

然后在入口文件中 require

require("@babel/register")
require("./app")

在入口文件頭部引入 @babel/register 后,我們的 app 文件中即可使用任意 es2015 的特性。

當(dāng)然,壞處是動態(tài)編譯,導(dǎo)致程序在速度、性能上有所損耗。(我們在啟動測試腳本的時候可以使用)

7. @babel/node

我們上面說,babel-register 提供動態(tài)編譯,能夠讓我們的源代碼真正運行在生產(chǎn)環(huán)境下 - 但其實不然,我們?nèi)孕枰霾糠终{(diào)整,比如新增一個入口文件,并在該文件中 require("@babel/register")。而 babel-node 能真正做到一行源代碼都不需要調(diào)整:

$ npm install --save-dev @babel/core @babel/node
$ npx babel-node app.js

只是,請不要在生產(chǎn)環(huán)境中使用 babel-node,因為它是動態(tài)編譯源代碼,應(yīng)用啟動速度非常慢

參考

http://babel.docschina.org/docs/en/babel-plugin-transform-runtime#technical-details

https://github.com/zloirock/core-js/blob/master/docs/2019-03-19-core-js-3-babel-and-a-look-into-the-future.md

https://blog.hhking.cn/2019/0...

https://segmentfault.com/a/11...

https://zhuanlan.zhihu.com/p/...

https://blog.zfanw.com/babel-...

https://www.thebasement.be/up...

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/105507.html

相關(guān)文章

  • babel相關(guān)總結(jié)

    對babel一直沒具體總結(jié)過,趁周末看了下文檔,記錄一下 babel作為一個compiler,主要用在轉(zhuǎn)換新的es標(biāo)準(zhǔn)實現(xiàn)來使所有瀏覽器都支持,這包含兩方面 新的es標(biāo)準(zhǔn)語法,箭頭函數(shù)、擴(kuò)展運算符、塊級作用域等 轉(zhuǎn)化新的es標(biāo)準(zhǔn)方法或正被提議還未納入標(biāo)準(zhǔn)的方法,,Array.from、Map、Promise、String.includes等 babel編譯過程 babel的編譯過程分為三個階段...

    Richard_Gao 評論0 收藏0
  • Babel 7 轉(zhuǎn)碼的正確姿勢

    摘要:轉(zhuǎn)碼的配置是每位前端童鞋在日常工作中都會遇到的。簡單點來說就是在轉(zhuǎn)碼過程中,對于一些新語法,都會抽象一個個小的函數(shù),在轉(zhuǎn)碼過程中完成替換。以上即是我總結(jié)的轉(zhuǎn)碼姿勢,如果對本篇有疑問或建議,歡迎在這里提出。 Babel 轉(zhuǎn)碼的配置是每位前端童鞋在日常工作中都會遇到的。剛開始我也是在網(wǎng)上搜索各種配置方法,升級到 Babel 7 的時候又折騰了一把,所以決定把自己的心得和理解記錄下來,希望能...

    JohnLui 評論0 收藏0
  • 從搭建腳手架到在npm上發(fā)布react組件

    摘要:從搭建腳手架到在上發(fā)布組件最近公司給公司里架設(shè)了私有的倉庫,相應(yīng)地也需要一個用來發(fā)布組件用的腳手架,在這個過程中又又又又復(fù)習(xí)了一下,在這里分享下腳手架搭建的過程。 從搭建腳手架到在npm上發(fā)布react組件 最近公司給公司里架設(shè)了私有的npm倉庫,相應(yīng)地也需要一個用來發(fā)布react組件用的腳手架,在這個過程中又又又又復(fù)習(xí)了一下webpack,在這里分享下腳手架搭建的過程。 首先,我們預(yù)...

    junfeng777 評論0 收藏0
  • vuex總結(jié)

    摘要:最近用了,遇到一個小問題在使用對象展開運算符的時候報錯,說找不到,但是明明已經(jīng)引用了,如下在網(wǎng)上查閱了問題,發(fā)現(xiàn)是的問題,的配置文件沒有寫當(dāng)然需要先安裝這些包這樣就可以愉快地使用對象擴(kuò)展運算符來用了 最近用了vuex,遇到一個小問題:在使用對象展開運算符...mapState,...mapAction的時候報錯,說找不到,但是明明已經(jīng)引用了,如下: showImg(https://se...

    fasss 評論0 收藏0
  • babel使用方法總結(jié)

    摘要:在項目根目錄下創(chuàng)建一個文件,注意這是個配置文件,以點號開頭,沒有后綴。提供了一種可以在瀏覽器中使用的方法,只需兩步就能一勞永逸。 1.在命令行中使用 Babel Babel 官方推薦將 Babel 安裝在本地,因為 Babel 的不同版本以及不同轉(zhuǎn)碼規(guī)則會起到不同的效果,全局安裝會帶來不必要的麻煩。在命令提示符中轉(zhuǎn)到自己的項目目錄下: npm install --save-dev ba...

    沈儉 評論0 收藏0

發(fā)表評論

0條評論

閱讀需要支付1元查看
<