摘要:為了方便,團隊將一些集合在一起,并稱之為。先看一下直觀體驗源代碼配置編譯后的代碼通過對比可以看出,第二種方案直接從引入,避免自己定義,從而減少代碼的體積。
Babel
Babel 是一個 JavaScript 編譯器,它可以將ES6+語法編譯為瀏覽器支持的ES5語法。要學好babel必須先理解相關的概念,但是你剛起步就去扣這些細節的話,很可能因為babel一些復雜而模糊的概念打擊你的信息。所以我們先從最簡單的開始,然后深入。
最簡單的例子接下來我們嘗試按照官方文檔做一個最簡單的例子
安裝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);
執行 npm run build,我們發現編譯后的文件沒有發生任何的改變,就是簡單的原樣輸出
// /lib/main.js const fetch = args => args; console.log(Promise);
為什么呢?這是因為在.babelrc文件沒有做任何的配置。我們一共使用了三個新特性,分別是常量申明const ,箭頭函數=>,新全局變量Promise。接下來我門嘗試將他們編譯為ES5代碼。
如上圖所示,借助plugin可以實現我們的目標。接下來我們分別實現它:
const
原文鏈接 文檔中說明:
babel-plugin-check-es2015-constants 這個插件僅僅是驗證const變量的規則,比如不能重復申明,不可變等特性。
把它編譯為ES5代碼需要借助babel-plugin-transform-es2015-block-scoping
我們設置需要編譯的代碼為:
const fetch = args => args; fetch = 55; // 故意寫錯 console.log(Promise);
安裝上面所需的兩個plugin并改寫.babelrc配置:
{ "presets": [], "plugins": [ "check-es2015-constants", "transform-es2015-block-scoping" ] }
編譯過程報錯驗證check-es2015-constants生效
我們修改需要編譯的代碼為:
const fetch = args => args; console.log(Promise);
再次編譯成功
var fetch = args => args; console.log(Promise);
到這里我們已經成功的使用插件對const的語法和轉譯(Syntax和 transform)ES5化。是不是很開心呢? 接下來我們處理箭頭函數=>。
arrow functions
同樣安裝對應的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" ] }
編譯結果:
var fetch = function (args) { return args; }; console.log(Promise);
編譯成功,unbelievable, we did it!!!,是不是真的很簡單?先別得意???,還有一個Promise沒有解決呢。有驚喜喲!!!
Promise
我有一個問題:我特意將上面的兩個例子放在一起,是因為他們都屬于對新語法Syntax進行編譯,而Promise是作為一個全局api的存在,在大部分瀏覽器中是不存在這個全局api的,如果讓你來解決這個問題,你會怎么做?
你的答案:是的,沒錯!就是在不支持Promise的環境中實現Promise,在babel中被稱為polyfill,注意它和shim的區別哦~
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. ---在入口文件的最頂層作用域直接引入
到這里我們已經完成既定的3個目標,但是你有沒有想過,隨著我們ES6新特性的增加,plugin的長度也逐漸增加,可以遇見會有多長?,而且自己去找這些對應的plugin也是比較麻煩的。有沒有傻瓜式的集成方法呢?您接著往下看。
Preset為了方便,Babel團隊將一些Plugins集合在一起,并稱之為preset。所以一個preset是一系列plugin的總和。按照年份劃分:
ES2015/ ES-2016/ES2017 等等,還延伸了stage的概念,詳情請查閱官網。
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代碼,按照你指定的運行環境。具體的配置項請看官網。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).
不需要做任何配置選項,它和babel-preset-latest表現一致,或者說和babel-preset-es2015, babel-preset-es2016, babel-preset-es20174個preset總和一致。
感覺是不是很牛逼!下面我們來嘗試一個例子。為防止有任何的代碼污染,我卸載所有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": {} }
我安裝時發現@babel/preset-env還處于bate版本,使用時還有一些問題,所以決定還是使用老版本。
(1)安裝babel-preset-env
上圖為babel-preset-env的一些依賴,主要為一些helper和plugin。
為了驗證出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)編譯結果
"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官網文檔
babel為源代碼非實例方法(比如Object.assign)和 babel-runtime/helps下的工具函數自動引用了polyfill。這樣可以避免全局空間的污染,非常適合用于JS庫和工具包的實現。但是實例方法(比如someString.includes("target"))還是需要使用babel-polyfill。
如果你是新手,你可能沒有注意到,babel編譯時會在每個文件生成一些需要幫助函數,如果文件比較多,那么這些重復的代碼會增加編譯后的代碼體積。下面是一個例子:
源代碼
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就是一個內部生成的幫助函數
為了優化編譯體積,babel 團隊推出了 babel-plugin-transform-runtime + babel-runtime來解決這個問題。先看一下直觀體驗:
源代碼
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); };
通過對比可以看出,第二種方案直接從babel-runtime引入babel-runtime/helpers/classCallCheck,避免自己定義,從而減少代碼的體積。
除了這個優點意外
babel-runtime
三個主要部分:core.js + helpers+ regenerator
當然除了上面的方法,通過按需引入 polyfills 和 transforms更能帶來更多的體積優化。
減少對不必要瀏覽器的兼容來減少 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)可能你發現了我并沒有安裝babel-cli,為什么我能使用babel命令?
因為我在全局安裝了babel。
(2) browserslistrc 配置更改之后 babel編譯后的代碼怎么沒有改變。或者說 browserslistrc 影響babel編譯的具體表現是怎么樣的?
暫時我也不知道,我正在研究,后面更新。
參考[1] browserslist
[2] browserslist-example
[3] browserslist-queries
由于本人表達能力真的很差,表達不夠清楚還望大家多多包涵。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/94563.html
摘要:快速體驗安裝依賴新建文件夾,在命令行里進入該文件夾,并執行如下命令生成文件是內置的一個,可通過命令行操作來編譯文件。入門為了確保轉換后的代碼能正常的運行,最好在代碼之前引入這是一個實現了部分特性的包。參考中文網入門 簡介 Babel 是一個 JavaScript 編譯器,可將我們代碼中的 ES6 語法轉換為 ES5 的語法,使我們的代碼能在不支持 ES6 語法的環境中正常運行。配合一些...
摘要:首先安裝使用時在文件頭加載然后,就不需要手動對轉碼了。 原文轉載自阮一峰教程 本文講解如何在nodejs環境下使用babel將ES6代碼轉ES5以及運行ES6的js文件 配置.babelrc文件 首先安裝es2015的presets字段 $ npm install --save-dev babel-preset-es2015 然后寫入.babelrc { presets:[ ...
摘要:入門什么是是一個廣泛使用的轉碼器,可以將代碼轉為代碼,從而在現有環境執行。 babel6 入門 什么是babel Babel是一個廣泛使用的轉碼器,可以將ES6代碼轉為ES5代碼,從而在現有環境執行。 因為es6比es5的代碼更為適合編寫程序,但是因為歷史的原因,現在普遍的瀏覽器并不支持es6代碼(普遍支持es5),即如果你寫es6代碼之后,在瀏覽器上運行出錯,因為瀏覽器的javas...
摘要:雖然夠好用,奈何沒有瀏覽器對其可以完全支持,本文書寫時間,開發版號稱已經支持的特性。開始安裝本系列假定讀者都有使用經驗,如果還沒有,趕緊去這里了解并安裝吧。到此,我們的已經準備就緒。 通過前面章節的講解,大家對ES2015的一些新語法有了初步的理解,之前我們的測試代碼都可以直接放入 Chrome Console 中直接運行,為了更好的學習后面的面向對象和模塊開發,我先用一章介紹一下 B...
摘要:概述開坑系列文章,不知道會寫到什么程度,畢竟寫文章并不在行,存在當做筆記做,先不講理論,實踐先行。 0x000 概述 開坑 react 系列文章,不知道會寫到什么程度,畢竟寫文章并不在行,存在當做筆記做,先不講理論,實踐先行。 0x001 創建項目 $ mkdir 0x001-helloworld $ cd 0x001-helloworld $ yarn init -y 0x0002 ...
閱讀 1756·2021-11-24 09:39
閱讀 1686·2021-11-22 15:22
閱讀 1002·2021-09-27 13:36
閱讀 3230·2021-09-24 10:34
閱讀 3329·2021-07-26 23:38
閱讀 2633·2019-08-29 16:44
閱讀 974·2019-08-29 16:39
閱讀 1104·2019-08-29 16:20