<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                &emsp;&emsp;Babel是一個JavaScript編譯器,不僅能將當前運行環境不支持的JavaScript語法(例如ES6、ES7等)編譯成向下兼容的可用語法(例如ES3或ES5),這其中會涉及新語法的轉換和缺失特性的修補;還支持語法擴展,從而能隨時隨地的使用JSX、TypeScript等語法。目前最新版本是7.4,自從6.0以來,Babel被分解的更加模塊化,各種轉譯功能都以插件的形式分離出來,可按自己的需求,靈活配置。 &emsp;&emsp;在7.0版本中,對Babel的包做了一次大調整,統一改成域級包,將原先以“babel-”為前綴的包遷移到@babel的命名空間,例如@babel/core、@babel/cli等。這種模塊化的設計,既能區分是否是官方發布的,也能避免命名沖突。 ## 一、@babel/core &emsp;&emsp;如果要以編程的方式使用Babel,那么可以通過@babel/core實現,安裝命令如下所示。 ~~~ npm install --save-dev @babel/core ~~~ &emsp;&emsp;在引入該包后,就能在JavaScript文件中直接編譯代碼、文件或AST。以編譯代碼為例,可選擇的方法有三個,如下所示。 ~~~ var babel = require("@babel/core"); babel.transform(code, options, function(err, result) { console.log(result);   // => { code, map, ast } }); babel.transformSync(code, options) // => { code, map, ast } babel.transformAsync(code, options) // => Promise<{ code, map, ast }> ~~~ &emsp;&emsp;雖然transform()用于異步編譯,transformSync()用于同步編譯,但是它們得到的結果相同,都是一個由轉換后的代碼(code)、源碼映射信息(map)和抽象語法樹(ast)組成的對象。而transformAsync()得到的結果與前面兩個方法不同,它返回一個包含code、map和ast的Promise對象。這些方法的第二個options參數,可用于傳遞配置信息,具體可參考[官方文檔](https://www.babeljs.cn/docs/options)。 &emsp;&emsp;如果要編譯文件或AST,那么也有類似的三個方法可供選擇。除了能編譯之外,利用這個包還能把代碼解析成AST(即傳入一段代碼,得到一個AST)以便其它插件對其進行語法分析,可使用的方法有parse()、parseSync()和parseAsync()。 ## 二、@babel/cli &emsp;&emsp;@babel/cli是一個Babel內置的命令行工具,可通過命令來編譯文件,其安裝如下所示。 ~~~ npm install --save-dev @babel/cli ~~~ &emsp;&emsp;假設有一個src.js文件,其內容如下代碼所示,用到了ES6中的箭頭函數。 ~~~ let fn = () => true; ~~~ &emsp;&emsp;在運行下面的命令后,可以看到輸出和輸入的代碼相同,這是因為此時還未指定任何轉譯插件。 ~~~ ./node_modules/.bin/babel src.js ~~~ &emsp;&emsp;如果當前的npm版本是5.2以上,那么可將./node\_modules/.bin縮短為npx,如下所示。 ~~~ npx babel src.js ~~~ &emsp;&emsp;在babel中,有多個可用的參數,下面只列舉其中的四個,其余參數的用法可參考[官方文檔](https://www.babeljs.cn/docs/babel-cli)。 ~~~ npx babel src --out-dir dist npx babel src.js --out-file dist.js npx babel src.js --out-file dist.js --plugins=@babel/plugin-transform-classes,@babel/transform-modules-amd npx babel src.js --out-file dist.js --presets=@babel/preset-env,@babel/flow ~~~ &emsp;&emsp;(1)“--out-dir”參數可編譯整個src目錄下的文件并輸出到dist目錄中。 &emsp;&emsp;(2)“--out-file”參數可編譯src.js文件并輸出到dist.js文件中。 &emsp;&emsp;(3)“--plugins”參數可指定編譯過程中要使用的插件,多個插件用逗號隔開。 &emsp;&emsp;(4)“--presets”參數可指定編譯過程中要使用的預設,多個預設用逗號隔開。 &emsp;&emsp;在package.json文件中,可以通過scripts字段聲明腳本命令。如果想要簡化babel命令,那么可以將它們遷移到scripts字段中,如下所示。 ~~~ { "scripts": { "compile": "npx babel src.js --out-file dist.js" } } ~~~ &emsp;&emsp;現在要編譯目錄的話,只要執行下面的這條npm命令即可。 ~~~ npm run compile ~~~ ## 三、配置 &emsp;&emsp;在Babel中,可以將各種命令的參數集中到一個配置文件中,而可配置的文件包括babel.config.js、.babelrc和package.json。 **1)babel.config.js** &emsp;&emsp;這是Babel 7最新引入的配置文件,存在于根目錄中(即package.json文件所在的目錄)。它不僅能以編程的方式聲明全局生效的[配置參數](https://www.babeljs.cn/docs/config-files#project-wide-configuration),還能利用overrides字段對不同的子目錄進行針對性的配置,從而就能避免為相關目錄創建一個.babelrc文件了。在下面的示例中,為test目錄單獨配置了預設(presets)。 ~~~ module.exports = { presets: [...], overrides: [{ test: ["./test"], presets: [...] }] }; ~~~ &emsp;&emsp;當運行下面兩條命令進行編譯時,第一條讀取的是最外層的預設,第二條讀取的是overrides中的預設。 ~~~ npx babel src.js npx babel ./test/src.js ~~~ **2).babelrc** &emsp;&emsp;babel.config.js并不是.babelrc的替代品,.babelrc文件用于局部配置(如下代碼所示),可放置于所有目錄中。如果當前目錄沒有.babelrc文件,那么就會往上查找直至找到為止。 ~~~ { "presets": [...] } ~~~ &emsp;&emsp;注意,如果.babelrc的后綴是“.js”(即.babelrc.js),那么在文件中可以通過JavaScript配置參數。 **3)package.json** &emsp;&emsp;在package.json文件中,可以聲明一個babel字段,其值就是.babelrc文件中的[配置參數](https://www.babeljs.cn/docs/config-files#file-relative-configuration),如下所示。 ~~~ { "babel": { "presets": [...] } } ~~~ &emsp;&emsp;注意,不能讓.babelrc和聲明過babel字段的package.json處在相同的目錄中。 **4)配置函數或方法** &emsp;&emsp;前面三種都是用單獨的文件來配置Babel的參數,其實還可以通過相關的函數或方法來達到相同地目的。在下面的示例中,引入gulp-babel包后就能通過得到的babel()函數來配置Babel的參數。 ~~~ let babel = require("gulp-babel"); babel({ presets: [...] }); ~~~ ## 四、插件 &emsp;&emsp;Babel的編譯可分為三個階段:解析、轉換和生成,而插件(Plugin)在轉換過程中起到了至關重要的作用。借助Babel的插件可將解析完成的AST按照特定的要求進行處理,然后再輸出生成的代碼。 **1)插件類型** &emsp;&emsp;Babel中的插件分為兩種類型:語法和轉換。語法插件只允許Babel解析成特定類型的語法,例如JSX、Flow等。轉換插件常用來編譯ES6、ES7、React和Modules等,由于能自動開啟相應的語法插件,因此不用顯式的指定兩種插件。以之前的箭頭函數為例,如果要將其編譯成所有瀏覽器都能識別的形式,那么就得安裝相應的插件,如下所示。 ~~~ npm install --save-dev @babel/plugin-transform-arrow-functions ~~~ &emsp;&emsp;在.babelrc文件中的配置如下所示。 ~~~ { "plugins": ["@babel/plugin-transform-arrow-functions"] } ~~~ &emsp;&emsp;在配置文件中,不僅能指定插件的相對或絕對路徑,還可省略插件名稱中的“babel-plugin-”前綴。假設有個插件名叫@org/babel-plugin-name,那么它的相對路徑和簡寫名稱如下所示。 ~~~ { "plugins": [ "../@org/babel-plugin-name", "@org/name" ] } ~~~ **2)執行順序** &emsp;&emsp;插件的執行順序會受配置時所處的位置的影響,具體規則如下所列,其中預設是指官方預先設計的一組插件集,本質上仍然是插件。 &emsp;&emsp;(1)插件執行在預設之前。 &emsp;&emsp;(2)插件會按順序從前往后執行。 &emsp;&emsp;(3)預設與插件相反,從后往前執行。 &emsp;&emsp;以下面的配置信息為例,在插件中,先執行@babel/plugin-transform-arrow-functions,后執行@babel/plugin-transform-classes。而在預設中,先執行@babel/preset-react,后執行@babel/preset-env。 ~~~ { "plugins": ["@babel/plugin-transform-arrow-functions", "@babel/plugin-transform-classes"], "presets": ["@babel/preset-env", "@babel/preset-react"] } ~~~ **3)插件參數** &emsp;&emsp;如果要配置插件的參數,那么得在插件名稱后增加一個參數對象,并且寫成數組的形式,如下所示。 ~~~ { "plugins": [ ["@babel/plugin-transform-arrow-functions", { "spec": true }], ["@babel/plugin-transform-classes", { "loose": true }] ] } ~~~ &emsp;&emsp;預設也能接收參數,其寫法與之類似。 ## 五、預設 &emsp;&emsp;如果在配置文件中一個一個的聲明插件,那么不僅會讓該文件變得巨大,而且還難免會有所遺漏。官方為了避免此類問題,引入了預設(Preset)的概念。預設類似于生活中的套餐,每個套餐會集合不同的插件,從而能夠一次性安裝各類插件,并且還可共享配置的參數。 **1)@babel/preset-env** &emsp;&emsp;此預設不僅集合了最新的ES語法(即編譯指定的ES標準),還能配置所要支持的平臺(例如Node、Chrome等)和版本,以及按需加載插件,其安裝命令如下所示。 ~~~ npm install --save-dev @babel/preset-env ~~~ &emsp;&emsp;下面是一個預設的配置示例,支持Chrome 58和IE 11,以及超過市場份額5%的瀏覽器。還有許多其它可供選擇的配置參數,具體可翻閱[官方文檔](https://www.babeljs.cn/docs/babel-preset-env)。 ~~~ { presets: [ [ "@babel/preset-env", { targets: { chrome: "58", ie: "11", browsers: "> 5%" } } ] ] } ~~~ &emsp;&emsp;除了@babel/preset-env之外,官方還給出了其它實用的預設,例如@babel/preset-flow、@babel/preset-react和@babel/preset-typescript等。 &emsp;&emsp;與插件類似,預設也能指定相對或絕對路徑,只不過它省略的前綴是“babel-preset-”。假設有個預設名叫@org/babel-preset-name,那么它的相對路徑和簡寫名稱如下所示。 ~~~ { "presets": [ "../@org/babel-preset-name", "@org/name" ] } ~~~ **2)stage-x** &emsp;&emsp;這是一組實驗性質的預設,囊括了處于提案階段的標準,TC39委員會將提案分為5個階段,如表2所示。 :-: ![](https://img.kancloud.cn/fa/83/fa83507f599e86c1231f1e88bb55cebe_1837x450.png) 表2 提案的五個階段 &emsp;&emsp;以上4個階段的預設存在著依賴關系,階段靠前的依賴階段靠后的(即數字小的包含數字大的),例如@babel/preset-stage-0依賴@babel/preset-stage-1。 &emsp;&emsp;由于這些提案階段的預設不太穩定,很有可能會被TC39委員會除名或變更,并且混合使用在配置上容易出錯,因此從Babel 7開始,它們都將被廢棄。 ## 六、@babel/polyfill &emsp;&emsp;雖然env預設(@babel/preset-env)能統一JavaScript的新語法(即高版本編譯成低版本),但是無法支持內置的新方法或新對象,例如Promise、Array.of()等。為此,Babel引入了的Polyfill技術(全部打包在@babel/polyfill中),將所缺的特性添加到全局對象中或內置對象的原型上,彌補env預設的不足,從而模擬出完整的ES6+語法和特性。 &emsp;&emsp;@babel/polyfill包含兩個模塊:regenerator-runtime和[core-js](https://github.com/zloirock/core-js),前者用于編譯生成器與異步函數(async和await),后者用于處理其它兼容性問題。@babel/polyfill的安裝命令如下所示,注意,使用的參數是--save而不是--save-dev,因為需要在源碼之前先執行Polyfill。 ~~~ npm install --save @babel/polyfill ~~~ **1)useBuiltIns** &emsp;&emsp;在env預設中,存在一個與@babel/polyfill有緊密聯系的useBuiltIns參數,它有三個關鍵字可供選擇,分別是false、entry和usage,具體說明如下所列。 &emsp;&emsp;(1)false:默認值,不開啟Polyfill,顯式的配置如下所示。 ~~~ { presets: [ ["@babel/preset-env", { useBuiltIns: false }] ] } ~~~ &emsp;&emsp;(2)entry:加載運行環境(可在targets參數中聲明)所需的Polyfill,下面是一個使用Promise的例子。 ~~~ require("@babel/polyfill"); new Promise(); ~~~ &emsp;&emsp;當useBuiltIns參數的值為entry時,這段代碼在編譯后,就會引入許多不相干的JavaScript文件,造成資源的浪費,如下所示。 ~~~ require("core-js/modules/es6.promise"); require("core-js/modules/es6.array.fill"); require("core-js/modules/es6.math.trunc"); require("core-js/modules/es6.string.fixed"); ...... new Promise(); ~~~ &emsp;&emsp;(3)usage:自動加載源碼所需的Polyfill,仍然以Promise為例,如下代碼所示,不用再顯式的引入@babel/polyfill。 ~~~ new Promise(); ~~~ &emsp;&emsp;當useBuiltIns參數的值為usage時,這段代碼在編譯后,就會只引入需要的JavaScript文件,如下所示。 ~~~ require("core-js/modules/es6.promise"); require("core-js/modules/es6.object.to-string"); new Promise(); ~~~ ## 七、@babel/runtime &emsp;&emsp;@babel/runtime與@babel/polyfill類似,也是用來增強env預設的,只是它以非侵入式的輔助函數來填補平臺所沒有的特性,其安裝命令如下所示。 ~~~ npm install --save @babel/runtime ~~~ &emsp;&emsp;在Babel 7中還引入了一個@babel/runtime-corejs2,它比@babel/runtime多包含一個core-js模塊,即能夠編譯Promise、Symbol等。接下來以ES6的類為例,如下所示。 ~~~ class People { name() {} } ~~~ &emsp;&emsp;在將People類編譯后,得到的結果如下所示,省略了三個函數中的邏輯代碼。 ~~~ "use strict"; function _classCallCheck(instance, Constructor) { } function _defineProperties(target, props) { } function _createClass(Constructor, protoProps, staticProps) { } var People = /*#__PURE__*/ function () { function People() { _classCallCheck(this, People); } _createClass(People, [{ key: "name", value: function name() {} }]); return People; }(); ~~~ **1)@babel/plugin-transform-runtime** &emsp;&emsp;由于編譯生成的輔助函數會滯留在所使用的文件中,因此文件越多冗余的函數就越多。如果人工分離,那工作量將巨大,因此Babel提供了能自動將它們分離的@babel/plugin-transform-runtime插件,其安裝命令如下所示。 ~~~ npm install --save-dev @babel/plugin-transform-runtime ~~~ &emsp;&emsp;仍然以ES6的People類為例,先在配置文件中將其聲明,如下所示。 ~~~ { plugins: ["@babel/plugin-transform-runtime"] } ~~~ &emsp;&emsp;然后再將類編譯,三個輔助函數就能通過引入的方式得到,如下所示。 ~~~ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck")); var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass")); ~~~ ## 八、動態編譯 &emsp;&emsp;在Babel中有兩種方式實現動態編譯,分別是@babel/register和@babel/node,它們的安裝命令如下所示。 ~~~ npm install --save-dev @babel/register npm install --save-dev @babel/node ~~~ &emsp;&emsp;雖然動態編譯省去了手動操作,但是會損耗程序的速度和性能,因此不適合生產環境。 **1)@babel/register** &emsp;&emsp;在將其安裝后,就會為Node.js的require()函數增加一個鉤子。每當通過require()加載后綴為.es6、.es、.jsx、.mjs或.js的文件時,就能自動對其進行Babel編譯。接下來用一個例子來演示@babel/register的用法,首先創建一個src.js的文件,其代碼如下所示。 ~~~ module.exports = () => true; ~~~ &emsp;&emsp;然后創建一個default.js文件,引入@babel/register和之前的src.js,如下所示。 ~~~ require("@babel/register"); var code = require("./src.js"); console.log(code.toString()); ~~~ &emsp;&emsp;最后在命令行工具中輸入“node default.js”,打印出編譯后的匿名函數,如下所示。 ~~~ function () { return true; } ~~~ &emsp;&emsp;在@babel/register中,如果需要使用Polyfill,那么得逐個引入。還要注意,它默認不會編譯node\_modules目錄中的模塊,但是可以通過ignore參數修改忽略規則來覆蓋其行為。 &emsp;&emsp;ignore參數是一個由正則表達式和函數組成的數組(如下代碼所示),如果要讓文件不被編譯,那么得將其路徑與正則表達式匹配或函數返回true,其中函數的參數就是文件路徑。 ~~~ require("babel-register")({ ignore: [ /regex/, function(filepath) { return true; } ] }); ~~~ &emsp;&emsp;另外還有一個only參數,其值也是一個數組,同樣也用來設置文件不被編譯的條件。只是其規則與ignore參數正好相反,即路徑與正則表達式不匹配或函數返回false時,才不編譯。 &emsp;&emsp;@babel/register還可以接收其它參數,例如extensions、cache等,并且會合并配置文件中的信息,作為其參數傳遞進來。 **2)@babel/node** &emsp;&emsp;在Babel 7之前,@babel/cli會自帶babel-node命令,但之后,官方將其拆成一個單獨的包:@babel/node。與@babel/register不同,@babel/node不需要調整源碼,直接一個命令就能實現動態編譯,如下代碼所示,其中src就是之前的src.js文件。 ~~~ npx babel-node src ~~~ ***** > 原文出處: [博客園-前端利器躬行記](https://www.cnblogs.com/strick/category/1472499.html) [知乎專欄-前端利器躬行記](https://zhuanlan.zhihu.com/pwtool) 已建立一個微信前端交流群,如要進群,請先加微信號freedom20180706或掃描下面的二維碼,請求中需注明“看云加群”,在通過請求后就會把你拉進來。還搜集整理了一套[面試資料](https://github.com/pwstrick/daily),歡迎瀏覽。 ![](https://box.kancloud.cn/2e1f8ecf9512ecdd2fcaae8250e7d48a_430x430.jpg =200x200) 推薦一款前端監控腳本:[shin-monitor](https://github.com/pwstrick/shin-monitor),不僅能監控前端的錯誤、通信、打印等行為,還能計算各類性能參數,包括 FMP、LCP、FP 等。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看