摘要:為了方便,團(tuán)隊(duì)將一些集合在一起,并稱之為。先看一下直觀體驗(yàn)源代碼配置編譯后的代碼通過對(duì)比可以看出,第二種方案直接從引入,避免自己定義,從而減少代碼的體積。
Babel
Babel 是一個(gè) JavaScript 編譯器,它可以將ES6+語法編譯為瀏覽器支持的ES5語法。要學(xué)好babel必須先理解相關(guān)的概念,但是你剛起步就去扣這些細(xì)節(jié)的話,很可能因?yàn)?b>babel一些復(fù)雜而模糊的概念打擊你的信息。所以我們先從最簡單的開始,然后深入。
最簡單的例子接下來我們嘗試按照官方文檔做一個(gè)最簡單的例子
安裝babel-cli
npm install --save-dev babel-cli
添加babel編譯命令
"build": "babel src -d lib"
添加.babelrc配置文件
{ "presets": [], "plugins": [] }
添加JS文件
// /src/main.js const fetch = args => args; console.log(Promise);
執(zhí)行 npm run build,我們發(fā)現(xiàn)編譯后的文件沒有發(fā)生任何的改變,就是簡單的原樣輸出
// /lib/main.js const fetch = args => args; console.log(Promise);
為什么呢?這是因?yàn)樵?b>.babelrc文件沒有做任何的配置。我們一共使用了三個(gè)新特性,分別是常量申明const ,箭頭函數(shù)=>,新全局變量Promise。接下來我門嘗試將他們編譯為ES5代碼。
如上圖所示,借助plugin可以實(shí)現(xiàn)我們的目標(biāo)。接下來我們分別實(shí)現(xiàn)它:
const
原文鏈接 文檔中說明:
babel-plugin-check-es2015-constants 這個(gè)插件僅僅是驗(yàn)證const變量的規(guī)則,比如不能重復(fù)申明,不可變等特性。
把它編譯為ES5代碼需要借助babel-plugin-transform-es2015-block-scoping
我們?cè)O(shè)置需要編譯的代碼為:
const fetch = args => args; fetch = 55; // 故意寫錯(cuò) console.log(Promise);
安裝上面所需的兩個(gè)plugin并改寫.babelrc配置:
{ "presets": [], "plugins": [ "check-es2015-constants", "transform-es2015-block-scoping" ] }
編譯過程報(bào)錯(cuò)驗(yàn)證check-es2015-constants生效
我們修改需要編譯的代碼為:
const fetch = args => args; console.log(Promise);
再次編譯成功
var fetch = args => args; console.log(Promise);
到這里我們已經(jīng)成功的使用插件對(duì)const的語法和轉(zhuǎn)譯(Syntax和 transform)ES5化。是不是很開心呢? 接下來我們處理箭頭函數(shù)=>。
arrow functions
同樣安裝對(duì)應(yīng)的plugin :
npm install --save-dev babel-plugin-transform-es2015-arrow-functions
這里延用上面需要compile的源代碼:
var fetch = args => args; console.log(Promise);
改寫.babelrc配置文件:
{ "presets": [], "plugins": [ "check-es2015-constants", "transform-es2015-block-scoping", "transform-es2015-arrow-functions" ] }
編譯結(jié)果:
var fetch = function (args) { return args; }; console.log(Promise);
編譯成功,unbelievable, we did it!!!,是不是真的很簡單?先別得意???,還有一個(gè)Promise沒有解決呢。有驚喜喲?。?!
Promise
我有一個(gè)問題:我特意將上面的兩個(gè)例子放在一起,是因?yàn)樗麄兌紝儆趯?duì)新語法Syntax進(jìn)行編譯,而Promise是作為一個(gè)全局api的存在,在大部分瀏覽器中是不存在這個(gè)全局api的,如果讓你來解決這個(gè)問題,你會(huì)怎么做?
你的答案:是的,沒錯(cuò)!就是在不支持Promise的環(huán)境中實(shí)現(xiàn)Promise,在babel中被稱為polyfill,注意它和shim的區(qū)別哦~
babel-polyfill 文檔最簡單的使用:
npm install --save-dev babel-polyfill
Use it by requiring it at the top of the entry point to your application or in your bundler config. ---在入口文件的最頂層作用域直接引入
到這里我們已經(jīng)完成既定的3個(gè)目標(biāo),但是你有沒有想過,隨著我們ES6新特性的增加,plugin的長度也逐漸增加,可以遇見會(huì)有多長?,而且自己去找這些對(duì)應(yīng)的plugin也是比較麻煩的。有沒有傻瓜式的集成方法呢?您接著往下看。
Preset為了方便,Babel團(tuán)隊(duì)將一些Plugins集合在一起,并稱之為preset。所以一個(gè)preset是一系列plugin的總和。按照年份劃分:
ES2015/ ES-2016/ES2017 等等,還延伸了stage的概念,詳情請(qǐng)查閱官網(wǎng)。
babel-preset-envA Babel preset that compiles ES2015+ down to ES5 by automatically determining the Babel plugins and polyfills you need based on your targeted browser or runtime environments.
不需要指定任何的plugin和polyfill,Babel preset 可以將ES6+的新語法向下編譯為ES5代碼,按照你指定的運(yùn)行環(huán)境。具體的配置項(xiàng)請(qǐng)看官網(wǎng)。Without any configuration options, babel-preset-env behaves exactly the same as babel-preset-latest (or babel-preset-es2015, babel-preset-es2016, and babel-preset-es2017 together).
不需要做任何配置選項(xiàng),它和babel-preset-latest表現(xiàn)一致,或者說和babel-preset-es2015, babel-preset-es2016, babel-preset-es20174個(gè)preset總和一致。
感覺是不是很牛逼!下面我們來嘗試一個(gè)例子。為防止有任何的代碼污染,我卸載所有npm package
最初的樣子:
{ "name": "babelrc", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "echo "Error: no test specified" && exit 1", "build": "babel src -d lib" }, "author": "", "license": "ISC", "devDependencies": {} }
我安裝時(shí)發(fā)現(xiàn)@babel/preset-env還處于bate版本,使用時(shí)還有一些問題,所以決定還是使用老版本。
(1)安裝babel-preset-env
上圖為babel-preset-env的一些依賴,主要為一些helper和plugin。
為了驗(yàn)證出babel-preset-env的是否滿足要求,我新增了幾行包括ES6的代碼:
const fetch = args => args; console.log(Promise); // 新增一些代碼 class G { } let [a, b, c] = [1, 2, 3]; (async () => { await console.log(1) })();
(2)配置.babelrc
{ "presets": ["env"], "plugins": [] }
(3)編譯結(jié)果
"use strict"; function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } var fetch = function fetch(args) { return args; }; console.log(Promise); // 新增一些代碼 var G = function G() { _classCallCheck(this, G); }; var a = 1, b = 2, c = 3; _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee() { return regeneratorRuntime.wrap(function _callee$(_context) { while (1) { switch (_context.prev = _context.next) { case 0: _context.next = 2; return console.log(1); case 2: case "end": return _context.stop(); } } }, _callee, undefined); }))();
我就問還有誰???所有的新語法特性都被成功處理了。
Runtime官網(wǎng)文檔
babel為源代碼非實(shí)例方法(比如Object.assign)和 babel-runtime/helps下的工具函數(shù)自動(dòng)引用了polyfill。這樣可以避免全局空間的污染,非常適合用于JS庫和工具包的實(shí)現(xiàn)。但是實(shí)例方法(比如someString.includes("target"))還是需要使用babel-polyfill。
如果你是新手,你可能沒有注意到,babel編譯時(shí)會(huì)在每個(gè)文件生成一些需要幫助函數(shù),如果文件比較多,那么這些重復(fù)的代碼會(huì)增加編譯后的代碼體積。下面是一個(gè)例子:
源代碼
class G { }
.babelrc配置
{ "presets": ["env"], "plugins": [] }
編譯代碼
"use strict"; function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } var G = function G() { _classCallCheck(this, G); }; // _classCallCheck就是一個(gè)內(nèi)部生成的幫助函數(shù)
為了優(yōu)化編譯體積,babel 團(tuán)隊(duì)推出了 babel-plugin-transform-runtime + babel-runtime來解決這個(gè)問題。先看一下直觀體驗(yàn):
源代碼
class G { }
.babelrc配置
{ "presets": ["env"], "plugins": ["transform-runtime"] }
編譯后的代碼:
"use strict"; var _classCallCheck2 = require("babel-runtime/helpers/classCallCheck"); var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } var G = function G() { (0, _classCallCheck3.default)(this, G); };
通過對(duì)比可以看出,第二種方案直接從babel-runtime引入babel-runtime/helpers/classCallCheck,避免自己定義,從而減少代碼的體積。
除了這個(gè)優(yōu)點(diǎn)意外
babel-runtime
三個(gè)主要部分:core.js + helpers+ regenerator
當(dāng)然除了上面的方法,通過按需引入 polyfills 和 transforms更能帶來更多的體積優(yōu)化。
減少對(duì)不必要瀏覽器的兼容來減少 polyfills 和 transforms的引入:
{ "presets": [ ["env", { "targets": { // The % refers to the global coverage of users from browserslist "browsers": [ ">0.25%", "not ie 11", "not op_mini all"] } }] ] }答疑
(1)可能你發(fā)現(xiàn)了我并沒有安裝babel-cli,為什么我能使用babel命令?
因?yàn)槲以谌职惭b了babel。
(2) browserslistrc 配置更改之后 babel編譯后的代碼怎么沒有改變?;蛘哒f browserslistrc 影響babel編譯的具體表現(xiàn)是怎么樣的?
暫時(shí)我也不知道,我正在研究,后面更新。
參考[1] browserslist
[2] browserslist-example
[3] browserslist-queries
由于本人表達(dá)能力真的很差,表達(dá)不夠清楚還望大家多多包涵。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/94563.html
摘要:快速體驗(yàn)安裝依賴新建文件夾,在命令行里進(jìn)入該文件夾,并執(zhí)行如下命令生成文件是內(nèi)置的一個(gè),可通過命令行操作來編譯文件。入門為了確保轉(zhuǎn)換后的代碼能正常的運(yùn)行,最好在代碼之前引入這是一個(gè)實(shí)現(xiàn)了部分特性的包。參考中文網(wǎng)入門 簡介 Babel 是一個(gè) JavaScript 編譯器,可將我們代碼中的 ES6 語法轉(zhuǎn)換為 ES5 的語法,使我們的代碼能在不支持 ES6 語法的環(huán)境中正常運(yùn)行。配合一些...
摘要:首先安裝使用時(shí)在文件頭加載然后,就不需要手動(dòng)對(duì)轉(zhuǎn)碼了。 原文轉(zhuǎn)載自阮一峰教程 本文講解如何在nodejs環(huán)境下使用babel將ES6代碼轉(zhuǎn)ES5以及運(yùn)行ES6的js文件 配置.babelrc文件 首先安裝es2015的presets字段 $ npm install --save-dev babel-preset-es2015 然后寫入.babelrc { presets:[ ...
摘要:首先,作為入門的話,的用戶手冊(cè)是個(gè)很不錯(cuò)的選擇,里面基本覆蓋了使用的各方面。所以下面主要是我學(xué)習(xí)的一些筆記,姑且當(dāng)作是一篇入門吧。下面我們正式進(jìn)入正題。這也是最常用的一個(gè)用法之一。有兩個(gè)方式進(jìn)行配置。 首先,作為入門的話,Babel的用戶手冊(cè)是個(gè)很不錯(cuò)的選擇,里面基本覆蓋了Babel使用的各方面。所以下面主要是我學(xué)習(xí)Babel的一些筆記,姑且當(dāng)作是一篇入門吧。 Babel是什么 按照B...
摘要:入門什么是是一個(gè)廣泛使用的轉(zhuǎn)碼器,可以將代碼轉(zhuǎn)為代碼,從而在現(xiàn)有環(huán)境執(zhí)行。 babel6 入門 什么是babel Babel是一個(gè)廣泛使用的轉(zhuǎn)碼器,可以將ES6代碼轉(zhuǎn)為ES5代碼,從而在現(xiàn)有環(huán)境執(zhí)行。 因?yàn)閑s6比es5的代碼更為適合編寫程序,但是因?yàn)闅v史的原因,現(xiàn)在普遍的瀏覽器并不支持es6代碼(普遍支持es5),即如果你寫es6代碼之后,在瀏覽器上運(yùn)行出錯(cuò),因?yàn)闉g覽器的javas...
摘要:雖然夠好用,奈何沒有瀏覽器對(duì)其可以完全支持,本文書寫時(shí)間,開發(fā)版號(hào)稱已經(jīng)支持的特性。開始安裝本系列假定讀者都有使用經(jīng)驗(yàn),如果還沒有,趕緊去這里了解并安裝吧。到此,我們的已經(jīng)準(zhǔn)備就緒。 通過前面章節(jié)的講解,大家對(duì)ES2015的一些新語法有了初步的理解,之前我們的測(cè)試代碼都可以直接放入 Chrome Console 中直接運(yùn)行,為了更好的學(xué)習(xí)后面的面向?qū)ο蠛湍K開發(fā),我先用一章介紹一下 B...
摘要:概述開坑系列文章,不知道會(huì)寫到什么程度,畢竟寫文章并不在行,存在當(dāng)做筆記做,先不講理論,實(shí)踐先行。 0x000 概述 開坑 react 系列文章,不知道會(huì)寫到什么程度,畢竟寫文章并不在行,存在當(dāng)做筆記做,先不講理論,實(shí)踐先行。 0x001 創(chuàng)建項(xiàng)目 $ mkdir 0x001-helloworld $ cd 0x001-helloworld $ yarn init -y 0x0002 ...
閱讀 1790·2021-11-24 09:39
閱讀 1711·2021-11-22 15:22
閱讀 1034·2021-09-27 13:36
閱讀 3332·2021-09-24 10:34
閱讀 3365·2021-07-26 23:38
閱讀 2656·2019-08-29 16:44
閱讀 996·2019-08-29 16:39
閱讀 1133·2019-08-29 16:20