babel import语法 js_Babel 的理解
由于 markdown 排版問(wèn)題建議從掘金閱讀:https://juejin.cn/post/6902323049513615374
目錄
- 前言
- babel 是什么
- babel 能做什么
- 工作流程
- 解析 Parse
- 轉(zhuǎn)換 Transform
- 生成 Generator
- 使用方式
- babel-standalone
- 介紹
- 版本
- 示例
- 問(wèn)答
- 補(bǔ)充
- cli 命令
- 介紹
- 安裝
- 使用
- 問(wèn)答
- 作為構(gòu)建工具的插件
- 模塊介紹
- babel-node
- 版本升級(jí)
- 問(wèn)答
- 總結(jié)
前言
babel 是什么
Babel 是一個(gè) JavaScript 編譯器
這是babel 官網(wǎng)對(duì) babel 一句短而精的定義, 該如何理解這句話的含義呢?首先定義它為一個(gè)編譯器,其次只對(duì) JavaScript 語(yǔ)言負(fù)責(zé).
關(guān)于編譯器概念可參考維基百科https://bk.tw.lvfukeji.com/wiki/%E7%BC%96%E8%AF%91%E5%99%A8
babel 能做什么
這里我們只需要知道 babel 作為 JavaScript 編譯器的工作流程:解析->轉(zhuǎn)換->生成.
通俗的可以理解為 babel 負(fù)責(zé)把 JavaScript 高級(jí)語(yǔ)法、新增 API 轉(zhuǎn)換為低規(guī)范以保障能夠在低版本的環(huán)境下正常執(zhí)行,接下來(lái)我們看 babel 是如何工作的.
工作流程
解析 Parse
萬(wàn)事開(kāi)頭難,第一步的解析工作該由誰(shuí)完成?
babylon
Babylon 是一款 JavaScript 解析器.
babel 本身是不負(fù)責(zé)解析工作的,而是調(diào)用了 babylon.parse 方法對(duì)源碼進(jìn)行詞法解析生成 AST 樹(shù).
轉(zhuǎn)換 Transform
babel-traverse
babel-traverse 負(fù)責(zé)遍歷 AST 樹(shù)進(jìn)行增刪改的操作.
從第一步獲取到 AST 樹(shù)之后,調(diào)用 babel-traverse 庫(kù)提供的 traverse 方法對(duì)樹(shù)進(jìn)行更新.
babel-types
一個(gè)基于 AST 樹(shù)的工具庫(kù)(可對(duì)節(jié)點(diǎn)增刪改查校驗(yàn)).babel-traverse 對(duì) AST 樹(shù)進(jìn)行操作的時(shí)候便使用了此庫(kù).
生成 Generator
最后一步將更新之后的 AST 樹(shù)進(jìn)行生成代碼.
babel-generator
對(duì)外提供 generator 方法接收 ast 參數(shù)返回值為改變之后的源碼.
以上則是對(duì) babel 編譯器整個(gè)流程大概的描述信息.所以 babel 是由一系列動(dòng)作配合完成的.
使用方式
babel-standalone
介紹
由于 babel 是基于 node 環(huán)境下運(yùn)行,對(duì)于非 node 環(huán)境(如瀏覽器),babel-standalone這個(gè)開(kāi)源項(xiàng)目提供了 babel.min.js 可通過(guò)<script>方式引入使用.
題外話:babel-standalone已加入了babel大家族(上岸成為有編制一員),以后下載的 7.x 版本 babel 包內(nèi)可以看到它的身影.
版本
| 名稱 | 版本 | 體積 | 備注 | 在線地址 | | ------------ | ------ | ------ | ------ | ------------------------------------------------------- | | babel.js | 6.26.0 | 1.78MB | 未壓縮 | https://unpkg.com/babel-standalone@6.26.0/babel.js | | babel.min.js | 6.26.0 | 773KB | 已壓縮 | https://unpkg.com/babel-standalone@6.26.0/babel.min.js | | babel.js | 7.12.9 | 3.1MB | 未壓縮 | https://unpkg.com/@babel/standalone@7.12.9/babel.js | | babel.min.js | 7.12.9 | 1.6MB | 已壓縮 | https://unpkg.com/@babel/standalone@7.12.9/babel.min.js |
示例
- 示例一 es6 轉(zhuǎn)碼
- 使用<script>引入在線地址或者下載之后本地引用.
- 將編寫(xiě)的 es6 代碼放入<script type="text/babel">內(nèi),需要注意一點(diǎn)type 類型為 text/babel.
- 示例二 模擬在線實(shí)時(shí)轉(zhuǎn)碼用戶輸入的腳本
- 這種方式適用于一些在線轉(zhuǎn)碼的場(chǎng)景:
- babel 官網(wǎng)首頁(yè)
- babel-repl 在線轉(zhuǎn)碼
- JSFiddle
- JSBin
以上這些均引入babel.min.js(可能引入的名稱或版本不一樣)通過(guò)調(diào)用Babel對(duì)象提供的各種 API(如transform、disableScriptTags、transformScriptTags...)實(shí)現(xiàn)在線實(shí)時(shí)轉(zhuǎn)碼.
<!DOCTYPE html> <html><head><meta charset="utf-8" /><title>babel-standalone 模擬在線實(shí)時(shí)轉(zhuǎn)碼用戶輸入的腳本</title><script src="https://unpkg.com/@babel/standalone@7.12.9/babel.min.js"></script></head><body>輸入:<textarea id="input" style="width: 100%" rows="15">class UserInfo{constructor(name='張三') {this.name = name;}getUserName(){return `${this.name}`;}}const user=new UserInfo('張三');console.log(user.getUserName());</textarea>實(shí)時(shí)轉(zhuǎn)碼:<pre id="output"></pre><script>var inputEl = document.getElementById('input');var outputEl = document.getElementById('output');function transform() {try {outputEl.innerHTML = Babel.transform(inputEl.value, {presets: ['es2015',['stage-2',{decoratorsBeforeExport: false,},],],}).code;} catch (e) {outputEl.innerHTML = 'ERROR: ' + e.message;}}inputEl.addEventListener('keyup', transform, false);transform();</script></body> </html>- 示例三 import、export 的使用
以上示例都是通過(guò)內(nèi)嵌的方式在頁(yè)面直接寫(xiě) es6 代碼,但實(shí)際開(kāi)發(fā)中有可能需要以外鏈的方式引入腳本,所以我們看會(huì)遇到哪些問(wèn)題.
<!DOCTYPE html> <html><head><meta charset="utf-8" /><title>babel-standalone import、export 的使用</title><script src="https://unpkg.com/@babel/standalone@7.12.9/babel.min.js"></script></head><body><div id="output"></div><script type="text/babel" src="./index.js"></script></body> </html> // index.js const getMsg = () => {const name = 'Babel';document.getElementById('output').innerHTML = `Hello ${name} version:${Babel.version}`; }; getMsg();把示例一從內(nèi)嵌方式修改為外鏈引入腳本證明沒(méi)問(wèn)題.但我們不止編寫(xiě)一個(gè) index.js 腳本,對(duì)于使用 import、export 這些 es6 語(yǔ)法是否也支持?
<!DOCTYPE html> <html><head><meta charset="utf-8" /><title>babel-standalone import、export 的使用</title><script src="https://unpkg.com/@babel/standalone@7.12.9/babel.min.js"></script></head><body><div id="output"></div><script type="text/babel">export default {name: '小朋友',age: 18,};</script></body> </html>首先我們以內(nèi)嵌方式運(yùn)行之后拋錯(cuò)Uncaught ReferenceError: exports is not defined,這里拋出exports未定義而不是 es6 的export未定義,由此說(shuō)明內(nèi)部是要把 es6 代碼轉(zhuǎn)換 CommonJS 模塊規(guī)范(印證了前面介紹中提到過(guò)的由于 babel 是基于 node 環(huán)境下運(yùn)行),而我們是需要在瀏覽器執(zhí)行的,所以babel-standalone項(xiàng)目提供的babel.min.js包含了 babel 用到的所有插件(各種特性、規(guī)范),可以直接配置為 umd 模式即可.
6.x 版本配置data-plugins="transform-es2015-modules-umd"
7.x 版本配置data-plugins="transform-modules-umd"
<!DOCTYPE html> <html><head><meta charset="utf-8" /><title>babel-standalone import、export 的使用</title><script src="https://unpkg.com/@babel/standalone@7.12.9/babel.min.js"></script></head><body><div id="output"></div><script type="text/babel" data-plugins="transform-modules-umd">export default {name: '小朋友',age: 18,};</script></body> </html>既然可以定義export導(dǎo)出那該如何import導(dǎo)入呢?這里babel-standalone又給我們提供了data-module定義導(dǎo)出的模塊名稱,然后導(dǎo)入即可.
<!DOCTYPE html> <html><head><meta charset="utf-8" /><title>babel-standalone import、export 的使用</title><script src="https://unpkg.com/@babel/standalone@7.12.9/babel.min.js"></script></head><body><div id="output"></div><scripttype="text/babel"data-plugins="transform-modules-umd"data-module="userInfo">export default {name: '小朋友',age: 18,};</script><script type="text/babel" data-plugins="transform-modules-umd">import userInfo from 'userInfo';document.getElementById('output').innerHTML = `Hello ${userInfo.name}`;</script></body> </html>這一些似乎都沒(méi)發(fā)現(xiàn)問(wèn)題,難道真的沒(méi)有什么問(wèn)題?那直接修改為外鏈的方式呢.
<!DOCTYPE html> <html><head><meta charset="utf-8" /><title>babel-standalone import、export 的使用</title><script src="https://unpkg.com/@babel/standalone@7.12.9/babel.min.js"></script></head><body><div id="output"></div><scripttype="text/babel"data-plugins="transform-modules-umd"src="./userInfo.js"></script><script type="text/babel" data-plugins="transform-modules-umd">import userInfo from 'userInfo';document.getElementById('output').innerHTML = `Hello ${userInfo.name}`;</script></body> </html> // userInfo.js export default {name: '小朋友',age: 18, };如果仔細(xì)看上面這段代碼的話,有沒(méi)有發(fā)現(xiàn)script標(biāo)簽內(nèi)缺少了屬性data-module定義模塊名稱,依然可以正常執(zhí)行呢?
劃重點(diǎn),babel.min.js內(nèi)部獲取script標(biāo)簽之后對(duì)屬性做了判斷,如果有src屬性則使用屬性值作為模塊名稱(如src="./userInfo.js"最終以u(píng)serInfo作為模塊名稱),如果沒(méi)有src屬性則獲取data-module屬性值作為模塊名稱,所以如果使用外鏈方式的話是不需要data-module屬性的(即使配置了也無(wú)效).
上面示例演示了 export 可以使用外鏈的方式,那import又如何使用外鏈方式呢?
<!DOCTYPE html> <html><head><meta charset="utf-8" /><title>babel-standalone import、export 的使用</title><script src="https://unpkg.com/@babel/standalone@7.12.9/babel.min.js"></script></head><body><div id="output"></div><scripttype="text/babel"data-plugins="transform-modules-umd"src="./userInfo.js"></script><scripttype="text/babel"data-plugins="transform-modules-umd"src="./index.js"></script></body> </html> // userInfo.js export default {name: '小朋友',age: 18, }; // index.js import userInfo from 'userInfo'; document.getElementById('output').innerHTML = `Hello ${userInfo.name}`;import 的使用方式同export的方式是一樣的,這樣就完成了以外鏈的方式引入腳本.
問(wèn)答
感覺(jué)示例部分關(guān)于import export修改外鏈的方式一直提起有什么問(wèn)題,結(jié)尾也沒(méi)發(fā)現(xiàn)什么坑?說(shuō)這個(gè)問(wèn)題之前,大家是否考慮過(guò)如果沒(méi)有外鏈引入<script src="./userInfo.js">,只有<script src="./index.js">會(huì)怎樣?在index.js內(nèi)部已經(jīng)通過(guò)import userInfo from 'userInfo';導(dǎo)入,是否可以不需要外鏈的方式引入,如果import導(dǎo)入多個(gè) js 又會(huì)怎樣?
穩(wěn)住.所以拎到問(wèn)答部分單獨(dú)聊...
<!DOCTYPE html> <html><head><meta charset="utf-8" /><title>babel-standalone import、export 的使用</title><script src="https://unpkg.com/@babel/standalone@7.12.9/babel.min.js"></script></head><body><div id="output"></div><scripttype="text/babel"data-plugins="transform-modules-umd"src="./index.js"></script></body> </html> // index.js import userInfo from 'userInfo'; document.getElementById('output').innerHTML = `Hello ${userInfo.name}`;如上面的示例的,直接外鏈引入index.js,拋出Uncaught TypeError: Cannot read property 'name' of undefined錯(cuò)誤,原因是userInfo是undefined所以u(píng)serInfo.name也無(wú)法取到值.
那我們就從轉(zhuǎn)碼開(kāi)始入手.
// index.js 轉(zhuǎn)碼之后 (function (global, factory) {if (typeof define === 'function' && define.amd) {define(['userInfo'], factory);} else if (typeof exports !== 'undefined') {factory(require('userInfo'));} else {var mod = {exports: {},};factory(global.userInfo);global.index = mod.exports;} })(typeof globalThis !== 'undefined'? globalThis: typeof self !== 'undefined'? self: this,function (_userInfo) {'use strict';_userInfo = _interopRequireDefault(_userInfo);function _interopRequireDefault(obj) {return obj && obj.__esModule ? obj : { default: obj };}document.getElementById('output').innerHTML = 'Hello '.concat(_userInfo['default'].name);} );我們對(duì)比一下index.js轉(zhuǎn)碼前后:
| 轉(zhuǎn)碼前 | 轉(zhuǎn)碼后 | | ---------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- | | import userInfo from 'userInfo'; | _userInfo = _interopRequireDefault(_userInfo); function _interopRequireDefault(obj) {return obj && obj.__esModule ? obj : { default: obj };} |
我們看到轉(zhuǎn)碼之后的代碼通過(guò)_interopRequireDefault(_userInfo)函數(shù)對(duì)_userInfo重新賦值的操作.(_interopRequireDefault函數(shù)的作用判斷對(duì)象是否需要添加default屬性).
劃重點(diǎn):這里插一段為什么會(huì)有__esModule和default屬性,首先在本節(jié)開(kāi)頭提到過(guò)由于 babel 是基于 node 環(huán)境下運(yùn)行,所以 babel 是要把 es6 的模塊轉(zhuǎn)換為 CommonJS 的形式,那么就需要了解兩者的區(qū)別.
| | 導(dǎo)出 | 導(dǎo)入 | | -------- | ------------------------------- | ------------------------ | | es6 | exportexport default | import {}import | | CommonJS | module.exports | require |
通過(guò)對(duì)比發(fā)現(xiàn) es6 的導(dǎo)出、導(dǎo)入可以是多種形式,而 CommonJS 則是單一的對(duì)象導(dǎo)出、導(dǎo)入.所以 babel 要把 es6 轉(zhuǎn)換 CommonJS 的形式就需要一些輔助改動(dòng).
關(guān)于模塊對(duì)象添加__esModule屬性,是為了標(biāo)記此模塊是否被轉(zhuǎn)碼,如果有此屬性則直接調(diào)用模塊(exports)的default屬性導(dǎo)出對(duì)象(babel 會(huì)把 es6 的export default默認(rèn)導(dǎo)出對(duì)象轉(zhuǎn)碼為 exports.default的形式,同時(shí)這種寫(xiě)法又符合 CommonJS 的規(guī)范module.exports = exports.default),主要是做到 es6 轉(zhuǎn)碼后與 CommonJS 規(guī)范的一致性.
關(guān)于default屬性,上面介紹了是有__esModule屬性的情況下,如果沒(méi)有__esModule屬性說(shuō)明沒(méi)有對(duì)該模塊進(jìn)行轉(zhuǎn)換(有可能是一個(gè)第三方模塊)對(duì)于這種情況直接調(diào)用模塊(exports)的default屬性會(huì)為undefined,所以這種情況就直接返回一個(gè)對(duì)象并且該對(duì)象添加一個(gè)default屬性,把屬性值指向自己(如上面這句轉(zhuǎn)碼之后的代碼return obj && obj.__esModule ? obj : { default: obj })
快醒醒,這兩個(gè)屬性不是這里的重點(diǎn),還記得問(wèn)題是什么嗎?userInfo為什么是undefined,看完轉(zhuǎn)碼之后的代碼,我們只需要知道一點(diǎn)import只是導(dǎo)入而已,至于導(dǎo)入的對(duì)象是否存在,是不屬于轉(zhuǎn)碼的職責(zé)所在(轉(zhuǎn)碼不會(huì)檢測(cè)導(dǎo)入的對(duì)象否存在...),還是繼續(xù)查找userInfo在哪里定義的吧...
繼續(xù)看轉(zhuǎn)碼之后的代碼發(fā)現(xiàn)在開(kāi)頭有if...else if...else對(duì)各種環(huán)境(AMD、CommonJS、UMD)做判斷,由于我們是瀏覽器內(nèi)執(zhí)行(UMD 模式),所以進(jìn)入else里在global.userInfo全局對(duì)象上有個(gè)userInfo,至此得出一個(gè)結(jié)論,在外鏈方式引入的腳本內(nèi)直接使用import導(dǎo)入對(duì)象引用,而外部無(wú)任何聲明export,此對(duì)象是undefined(其實(shí)在 AMD 的define(['userInfo'], factory)、CommonJS 的require('userInfo')也是同理).
簡(jiǎn)單一句話:無(wú)論通過(guò)哪種形式引用,必須要聲明,所以外鏈的方式還是需要script聲明.
簡(jiǎn)單一句話:無(wú)論通過(guò)哪種形式引用,必須要聲明,所以外鏈的方式還是需要script聲明.
簡(jiǎn)單一句話:無(wú)論通過(guò)哪種形式引用,必須要聲明,所以外鏈的方式還是需要script聲明.
此處使用的聲明可能用詞不太準(zhǔn)確,但相信看到這里應(yīng)該可以意會(huì)到.
<!DOCTYPE html> <html><head><meta charset="utf-8" /><title>babel-standalone import、export 的使用</title><script src="https://unpkg.com/@babel/standalone@7.12.9/babel.min.js"></script></head><body><div id="output"></div><scripttype="text/babel"data-plugins="transform-modules-umd"src="./userInfo.js"></script><scripttype="text/babel"data-plugins="transform-modules-umd"src="./index.js"></script></body> </html> // userInfo.js export default {name: '小朋友',age: 18, }; // index.js import userInfo from 'userInfo'; document.getElementById('output').innerHTML = `Hello ${userInfo.name}`; // userInfo.js 轉(zhuǎn)碼后 (function (global, factory) {if (typeof define === 'function' && define.amd) {define(['exports'], factory);} else if (typeof exports !== 'undefined') {factory(exports);} else {var mod = {exports: {},};factory(mod.exports);global.userInfo = mod.exports;} })(typeof globalThis !== 'undefined'? globalThis: typeof self !== 'undefined'? self: this,function (_exports) {'use strict';Object.defineProperty(_exports, '__esModule', {value: true,});_exports['default'] = void 0;var _default = {name: '小朋友',age: 18,};_exports['default'] = _default;} ); // index.js 轉(zhuǎn)碼之后 (function (global, factory) {if (typeof define === 'function' && define.amd) {define(['userInfo'], factory);} else if (typeof exports !== 'undefined') {factory(require('userInfo'));} else {var mod = {exports: {},};factory(global.userInfo);global.index = mod.exports;} })(typeof globalThis !== 'undefined'? globalThis: typeof self !== 'undefined'? self: this,function (_userInfo) {'use strict';_userInfo = _interopRequireDefault(_userInfo);function _interopRequireDefault(obj) {return obj && obj.__esModule ? obj : { default: obj };}document.getElementById('output').innerHTML = 'Hello '.concat(_userInfo['default'].name);} );繼上一個(gè)問(wèn)題,如果外鏈引入了userInfo.js但index.js里沒(méi)有import userInfo from 'userInfo';又如何呢?對(duì)于這個(gè)問(wèn)題,請(qǐng)品一下,上面對(duì)__esModule和default屬性的介紹,就是那段這兩個(gè)屬性不是這里的重點(diǎn),現(xiàn)在是這個(gè)問(wèn)題的答案.
babel-standalone 如何使用多個(gè)import export.其實(shí)和上面的示例是一樣的,只需要外鏈多個(gè)script即可.
<!DOCTYPE html> <html><head><meta charset="utf-8" /><title>babel-standalone 如何使用多個(gè)import、export</title><script src="https://unpkg.com/@babel/standalone@7.12.9/babel.min.js"></script></head><body><div id="output"></div><scripttype="text/babel"data-plugins="transform-modules-umd"src="./other.js"></script><scripttype="text/babel"data-plugins="transform-modules-umd"src="./userInfo.js"></script><scripttype="text/babel"data-plugins="transform-modules-umd"src="./index.js"></script></body> </html> // other.js export function random() {return Math.floor(Math.random() * 10); }export const randomStr = '幸運(yùn)數(shù)字:'; // userInfo.js export default {name: '小朋友',age: 18, }; // index.js import { randomStr, random } from 'other'; import userInfo from 'userInfo'; function init() {document.getElementById('output').innerHTML = `Hello ${userInfo.name} ${randomStr} ${random()}`; }init();補(bǔ)充
對(duì)于開(kāi)發(fā)者來(lái)說(shuō)這種直接編寫(xiě) es6 代碼實(shí)時(shí)轉(zhuǎn)碼比較方便,同時(shí)也耗時(shí)影響性能,所以開(kāi)發(fā)環(huán)境可以使用,對(duì)于生產(chǎn)環(huán)境還是推薦加載轉(zhuǎn)碼之后的腳本.
You are using the in-browser Babel transformer. Be sure to precompile your scripts for production——官網(wǎng)建議.
cli
介紹
CLI:命令行界面(英語(yǔ):Command-Line Interface,縮寫(xiě):CLI)是在圖形用戶界面得到普及之前使用最為廣泛的用戶界面,它通常不支持鼠標(biāo),用戶通過(guò)鍵盤輸入指令,計(jì)算機(jī)接收到指令后,予以執(zhí)行.
關(guān)于 CLI 概念可參考維基百科https://bk.tw.lvfukeji.com/wiki/CLI
babel 內(nèi)置的 CLI, 可直接在命令行轉(zhuǎn)碼文件.
安裝
安裝 babel cli之前先檢查是否安裝node、npm(前面有提到過(guò) babel 是基于 node 環(huán)境下運(yùn)行,所以自行檢索安裝步驟).
babel cli分為以下兩種安裝方式:
建議局部安裝,且下面的使用示例均為局部安裝.
使用
在介紹使用之前,請(qǐng)先準(zhǔn)備好項(xiàng)目環(huán)境.
關(guān)于 package.json的相關(guān)配置可參考https://docs.npmjs.com/cli/v6/configuring-npm/package-json
接下來(lái)正式進(jìn)入babel cli的使用.
項(xiàng)目目錄結(jié)構(gòu)如下:
|--babel-cli 項(xiàng)目名稱|-- package.json // package.json {"name": "cli" }安裝完成之后項(xiàng)目目錄結(jié)構(gòu)如下:
|--babel-cli 項(xiàng)目名稱|-- package.json|-- package-lock.json 記錄安裝模塊的版本、來(lái)源信息|-- node_modules node 依賴模塊集合|-- babel-cli cli模塊|-- babel-* 以babel開(kāi)頭的各個(gè)模塊后面會(huì)介紹 // package.json {"name": "cli","devDependencies": {"babel-cli": "^6.26.0"} }至此所有的配置、安裝已完成,接下來(lái)我們?cè)陧?xiàng)目中創(chuàng)建一個(gè)腳本文件(script.js),并且執(zhí)行轉(zhuǎn)碼.
// script.js const hello = 'Hello';[1, 2, 3, 4].forEach((item) => console.log(item));執(zhí)行命令進(jìn)行轉(zhuǎn)碼...
- 轉(zhuǎn)碼輸出到 stdout(標(biāo)準(zhǔn)輸出).
npx babel script.js
- 轉(zhuǎn)碼輸出到指定文件.
npx babel script.js --out-file script-compiled.js
- 轉(zhuǎn)碼某個(gè)目錄到指定目錄
npx babel src --out-dir lib
以上就是關(guān)于babel cli的簡(jiǎn)單使用,更多配置可參考官網(wǎng)https://babel.docschina.org/docs/en/babel-cli/
問(wèn)答
全局安裝、局部安裝、npx、 npm 有什么區(qū)別?從安裝方式來(lái)說(shuō)babel cli有兩種(全局安裝、局部安裝)上面提到過(guò),安裝完之后如何執(zhí)行命令轉(zhuǎn)碼,同樣也分為兩種:
全局、局部唯一區(qū)別是查找的路徑不同.
全局、局部唯一區(qū)別是查找的路徑不同.
全局、局部唯一區(qū)別是查找的路徑不同.
接下來(lái)對(duì)比一下npx、npm的區(qū)別.
想要使用npm運(yùn)行命令轉(zhuǎn)碼則需要配置package.json的scripts對(duì)象,關(guān)于 scripts的相關(guān)配置可參考https://docs.npmjs.com/cli/v6/commands/npm-run-script
// package.json {"name": "cli","devDependencies": {"babel-cli": "^6.26.0"},"scripts": {"babel": "babel script.js","babel-compiled": "babel script.js --out-file script-compiled.js"} }如上面的使用示例可以通過(guò)配置package.json的scripts對(duì)象,命令行進(jìn)入項(xiàng)目目錄,通過(guò)執(zhí)行命令npm run babel 、 npm run babel-compiled實(shí)現(xiàn)轉(zhuǎn)碼.
如果不配置scripts對(duì)象就無(wú)法使用npm嗎?答案是可以的,使用起來(lái)稍微麻煩一點(diǎn),由于npm是查找的項(xiàng)目目錄下node_modules/.bin/babel命令執(zhí)行,所以我們可以在命令行手動(dòng)調(diào)用node_modules/.bin/babel scripts.js實(shí)現(xiàn)轉(zhuǎn)碼.
有什么辦法既可以不需要命令行每次都輸入node_modules/...這一堆,也不需要配置scripts對(duì)象.答案就是npx,它直接查找項(xiàng)目下的node_modules/.bin對(duì)應(yīng)的命令執(zhí)行,無(wú)需我們手動(dòng)輸入或配置scripts對(duì)象.(不信你看上面的使用部分,就是直接使用的npx).
即安裝了全局,又安裝了局部,npx、npm該如何查找node_modules?上面的一個(gè)問(wèn)題第 2 點(diǎn)提到查找當(dāng)前項(xiàng)目下的node_modules這是不嚴(yán)謹(jǐn)?shù)?應(yīng)該是由近到遠(yuǎn),如果項(xiàng)目沒(méi)有node_modules模塊集合,才查找全局.
為什么上面的使用示例輸出的代碼沒(méi)有轉(zhuǎn)碼?// 轉(zhuǎn)碼前 const hello = 'Hello';[1, 2, 3, 4].forEach((item) => console.log(item)); // 轉(zhuǎn)碼后 const hello = 'Hello';[1, 2, 3, 4].forEach((item) => console.log(item));這里只對(duì)babel cli做一個(gè)初步了解,關(guān)于(語(yǔ)法、新特性)轉(zhuǎn)碼、配置文件后面會(huì)介紹,另外如果開(kāi)發(fā)工具庫(kù)babel cli還是比較適合的.
作為構(gòu)建工具的插件
介紹
現(xiàn)在一些構(gòu)建工具集成了 babel 或提供了配置方式,這些插件只是配置方式不同,如同babel cli一樣 無(wú)論全局、局部(npx、npm)哪種方式最終的轉(zhuǎn)碼流程都是一樣,所以這里不對(duì)插件的配置使用做介紹.
webpack=>babel-loaderhttps://www.webpackjs.com/loaders/babel-loader/
gulp=>gulp-babelhttps://www.npmjs.com/package/gulp-babel
rollup=>rollup-plugin-babelhttps://github.com/rollup/rollup-plugin-babel
未完待續(xù).
總結(jié)
以上是生活随笔為你收集整理的babel import语法 js_Babel 的理解的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: linux手动生成dump文件权限不足_
- 下一篇: 网络部署过程中_郑州萤火云SEO网络优化