摘要:簡單的說就是,新語法編譯器舊語法。說明所以,對于新特性,我們可以通過使用,也可以通過語法轉化來達到兼容。
0x001 polyfill
我們都知道,js總是一直存在著兼容性問題,雖然其他語言也存在著兼容性問題,比如c++、java,但那種兼容性是新特性在舊版本上的不兼容,js則存在著各種奇形怪哉的不兼容。這其中有著非常復雜的歷史和時代的原因,并不加以累述。而解決兼容性問題的方法在以前只存在一種,那就是polyfill。先說什么是polyfill,比如我們想要用數組的一個新的方法includes,在較新版本的瀏覽器下,可以直接使用:
但是在舊的瀏覽器下,比如ie10,就會報錯:
這種情況下我們可以通過自定義一個方法來解決:
function includesPolyfill(){ if(!Array.prototype.includes){ Array.prototype.includes=function(element){ for(var i=0; i這里定義一個簡單的方法,添加到Array.prototype上,為了簡單,并沒有做太多的異常檢測,接著在代碼中引入以上方法并優先執行,就可以做到在不兼容這個方法的js環境總直接調用Array.protorype.includes方法了:
0x002 預編譯
這就是polyfill,但是polyfill有其局限性,對于可以用舊的方法實現的新特性,可以使用polyfill來解決,比如Array.prototype.includes,但是,對于一些無法使用舊方法實現的新特性、新語法,比如箭頭函數、const之類的,polyfill就無能為力了,這個時候需要使用另一種方法:預編譯,或者說是語法轉換。在之前的js開發中,是沒有預編譯這個流程的,擼完js就直接部署了,但是隨著前端工程化的推進,預編譯也就出現了,特別是typescript之類的語言出現以后,編碼和發布就不再是同一種方式了。
現在在發布之前,總是需要打包,而打包有許多的流程,比如資源整合、代碼優化、壓縮混淆...而在其中對代碼的操作上,我們可以將新的語法轉化成舊的語法來達到對新語法的支持。
簡單的說就是,新語法->編譯器->舊語法。
編譯器的作用就是將輸入的源碼中的新特性轉化成就語法,說白了就是字符串處理,比如對箭頭函數的處理:var add=(num1, num2)=>num1+num2,這段代碼在不兼容箭頭函數的環境中,比如ie10,是無法執行的
但是我們可以通過語法轉化、編譯處理,將源碼轉化成var add=function(num1, num2){return num1+num2},這樣在不支持箭頭函數的瀏覽器中就可以執行了現在來實現一個簡單的編譯器,當然只支持箭頭函數
function translate(src){ let [_, name, args, body]=src.match(/((.+))=>(.+)/) return `function ${name}(${args}){return ${body}}` }為了簡單,只是使用簡單的正則提取來做實驗,并且不做任何異常處理
translate("var add=(num1, num2)=>num1+num") // var add=function(num1, num2){return num1+num2}將轉化結果保存成文件,就可以在不兼容箭頭語法的環境中使用了。甚至我們可以在瀏覽器中嵌入這個編譯器,將源碼編譯之后使用Function構造函數或者eval來執行,達到執行新語法的作用,這種情況下,稱為運行時編譯器,當然一般不會這么用。
0x003 使用babel很明顯,不可能自己寫這么一個編譯器,那還要不要做項目了?這時候只能借助社區的力量了,babel就是這么一個東西,接下來將會使用babel來解析箭頭函數
初始化一個項目
$ mk babel-demo $ cd babel-demo $ npm init -y
安裝babel:
注意:(babel7以后babel相關的庫基本都是放在@babel命名空間下)$ npm install --save-dev @babel/core @babel/cli @babel/plugin-transform-arrow-functions@babel/core:核心庫
@babel/cli:命令行工具
@babel/plugin-transform-arrow-functions:箭頭函數語法轉化插件
編寫代碼:
var add=(num1, num2)=>num1+num2
使用babel解析
$ npx babel --plugins @babel/plugin-transform-arrow-functions index.js -o bundle.js上面命令的意思是將index.js使用babel轉化,并將結果放到bundle.js中,執行之后,將會生成bundle
--plugins:為這次轉化添加插件支持
-o:輸出文件
查看轉化結果
查看新生成的bundle.js,可以發現,箭頭函數被轉化成了普通的funciton, 在任何環境中都支持。var add = function (num1, num2) { return num1 + num2; };說明
0x004 babel配置文件
所以,對于新特性,我們可以通過使用polyfill,也可以通過語法轉化來達到兼容。很明顯,使用babel cli的局限性很大,容易出錯、不直觀、繁瑣等,所以babel還是支持配置文件的方式:
.babelrc方式
在項目新建.babelrc文件,并使用JSON語法配置
{ "presets": [...], "plugins": [...] }
直接寫在package.json的babel節點
{ "name": "my-package", "version": "1.0.0", "babel": { "presets": [ ... ], "plugins": [ ... ], } }
babel.config.js方式
module.exports = function () { const presets = [ ... ]; const plugins = [ ... ]; return { presets, plugins }; }兩種方式大同小異,區別就是一個是動態的,一個是靜態的,推薦小項目就用.babelrc,大項目就使用babel.config.js
0x005 babel配置之pluginplugin是babel中很重要的概念,可以說,plugin才是構成babel擴展性的核心,各種各樣的plugin構成了babel的生態,可以在這里看一些babel的插件列表。
.babelrc配置文件中配置插件
{ "plugins": ["@babel/plugin-transform-arrow-functions"] }這時候我們再執行npx babel index.js -o bundle.js,就可以不指定plugin也能正常轉化箭頭函數了
如果一個plugin可以配置參數,則可以這么配置:{ "plugins": [ ["@babel/plugin-transform-arrow-functions", { "spec": true }] ] }0x006 babel配置之preset在一個項目中,我們總是要配置一大堆的插件,這個時候,就是preset出馬的時候了,那什么是preset呢?其實就是預置插件列表了,引入了一個preset就包含了一個系列的plugin
比如preset-react就包含了以下插件:@babel/plugin-syntax-jsx
@babel/plugin-transform-react-jsx
@babel/plugin-transform-react-display-name
.babelrc配置preset-react
{ "presets": ["@babel/preset-react"] }
如果有配置項,就醬:
{ "presets": [ [ "@babel/preset-react", { "pragma": "dom", // default pragma is React.createElement "pragmaFrag": "DomFrag", // default is React.Fragment "throwIfNamespace": false // defaults to true } ] ] }0x007 babel和webpack
添加webpack.config.js
const path=requrie("path") module.exports={ entry:path.resolve(__dirname, "index.js"), output:{ path: path.resolve(__dirname, "dist"), filename:"bundle.js" }, module: { rules: [ { test: /.js$/, use: "babel-loader" } ] }- 添加相關依賴$ npm install --save-dev webpack webpack-cli babel-loader ``` - `webpack`:`webpack`核心庫 - `webpack-cli`:`webpack`命令行工具 - `babel-loader`:`babel`的`webpack loader`
打包
$ npm webpack
查看編譯結果
省略無關的東西,可以看到,箭頭函數也被轉化成了function/***/ "./index.js": /*!******************!* !*** ./index.js ***! ******************/ /*! no static exports found */ /***/ (function(module, exports) { eval("let add = function (num1, num2) { return num1 + num2; }; module.exports = add; //# sourceURL=webpack:///./index.js?"); /***/ }) /******/ });0x008 支持es6支持es6可以使用@babel/present-env來代替一系列的東西,還有許多的配置像,比如兼容的瀏覽器版本,具體可以看這里
安裝依賴包
$ npm install --save-dev @babel/preset-env
配置
{ "plugins": ["@babel/present-env"] }
打包
$ npm webpack
查看效果
/***/ "./index.js": /*!******************!* !*** ./index.js ***! ******************/ /*! no static exports found */ /***/ (function(module, exports) { eval("let add = function (num1, num2) { return num1 + num2; }; module.exports = add; //# sourceURL=webpack:///./index.js?"); /***/ }) /******/ });0x009 總結這只是babel功能的一個小覽,了解一下babel的基本使用和一些概念而已。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/99390.html
摘要:不信你命令行里敲個試試敲敲敲當然了想直接運行命令,你需要將添加到系統變量啊。全局安裝相同的,運行命令耐心等待安裝完成后,你的系統變量里就存在命令了,你可以運行下試試。上訴如果有不懂的,歡迎留言。 再一次見面! Light 還是太太太懶了,距離上一篇沒啥營養的文章已經過去好多天。今天為大家介紹介紹 webpack 最基本的概念,以及簡單的配置,讓你能快速得搭建一個可用的 webpack ...
摘要:當屬性是一個回調函數時,函數接收底層元素或類實例取決于元素的類型作為參數。 手挽手帶你學React入門第一期,帶你熟悉React的語法規則,消除對JSX的恐懼感,由于現在開發中都是使用ES6語法開發React,所以這次也使用ES6的模式進行教學,如果大家對ES6不熟悉的話,先去看看class相關內容吧,這里我也慢慢帶大家一步一步學會React。 視頻教程 視頻教程可移步我的個人博客:h...
摘要:本質就是一個編譯器,通過將源代碼解析成抽象語法樹將源代碼的結果一系列轉換生成目標代碼的將目標代碼的轉換成代碼。項目構建三開發環境本地服務器搭建源碼下載地址參考資料入門阮一峰中文文檔中文網 注:以下教程均在 windows 環境實現,使用其他操作系統的同學實踐過程可能會有些出入。 ??在上一章 webpack 項目構建:(一)基本架構搭建 我們搭建了一個最基本的 webpack 項目,現...
摘要:是目前最常用的轉的工具,但即使是,各瀏覽器的支持度也是不一的,因此便產生了本文,找出一些能夠被翻譯成兼容性高代碼的語法。不可用因為會使用到參考資料,用來查瀏覽器兼容性。到底將代碼轉換成什么鳥樣,感謝。官網試驗轉換后的代碼 前言 由于目前各瀏覽器對ES6兼容性較低,再加上需要兼容歷史上各種版本的瀏覽器,因此,使用編譯器將ES6語法轉譯成ES5語法則勢在必行了。babel是目前最常用的ES...
閱讀 3564·2021-11-16 11:45
閱讀 2099·2021-11-08 13:23
閱讀 2212·2021-10-11 10:59
閱讀 2892·2021-09-27 13:36
閱讀 2481·2019-08-30 15:54
閱讀 2669·2019-08-29 16:58
閱讀 2783·2019-08-29 16:56
閱讀 1343·2019-08-26 13:52