日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

babel6和babel7中关于polyfill和preset-env和babel-plugin-transform-runtime等总结

發布時間:2023/12/2 编程问答 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 babel6和babel7中关于polyfill和preset-env和babel-plugin-transform-runtime等总结 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

記錄自己零散的收獲,隨筆。

一些基礎

  • babel的作用是轉換JS新的特性代碼為大部分瀏覽器能運行的代碼。

  • babel轉碼又分為兩部分,一個是語法轉換,一個是API轉換。

  • 對于API的轉換又分為兩部分,一個是全局API例如Promise,Set,Map還有靜態方法Object.assign,另一個是實例方法例如Array.prototype.includes。對于實例方法core-js@2是轉換不了的,只有core-js@3才會轉換。

  • babel代碼轉換依賴plugin,沒有plugin的情況下babel做的事情只是 code => code。

  • plugin 有很多,一個個導入又特別麻煩,這時候我們又知道了preset。

  • preset是很多plugin的集合,配置如下:

    .babelrc文件

    {"presets": ["env"] }

    如果preset-env是有配置項的:

    {"presets": [["env",{// 這里就是配置項}]] }

    可以觀察出如果某個preset需要配置可以將字符串換成一個數組,第一項是preset的name,第二項就是options。plugin同preset。

    注:preset是從右往左執行,plugin是從左往右執行,并且plugin先于preset執行。

    babel6到babel7的升級是具有破壞性的,主要總結下polyfill的用法和在babel6和babel7中的不同。

    babel-polyfill

    上面說到babel主要做兩件事,一個是轉換語法,一個是兼容新的API。

    babel-polyfill 的作用是兼容新的API。

    babel7

    babel7進行了較大的改動,廢棄了 stage-x的preset,還增加了命名空間區分官方插件和非官方插件,@babel/core,@babel/cli等。

    建議使用@babel/preset-env 。

    @babel/plugin-transform-runtime

    該插件的引入主要有兩個作用

    在babel7中,原先的插件babel-plugin-transform-runtime也做了修改 -> @babel/plugin-transform-runtime。并且在功能上也變強大了。

    移除了polyfill的配置項添,加了corejs配置項。

    @babel/plugin-transform-runtime的默認配合如下:

    {plugins: [["@babel/plugin-transform-runtime", {"absoluteRuntime": false, // 不是很清除干啥的"corejs": false, // 下面詳解"helpers": true, // 助手函數是否提取,同babel-plugin-transform"regenerator": true, // 同babel-plugin-transform"useESModules": false}]] }

    對于配置項 corejs: false | 2 | 3。

    false 依賴 @babel/runtime,是默認選項,認為需要填充的API以被填充,所以不對API作polyfill(對于@babel/runtime的依賴是提取的helper的依賴)。
    2 依賴@babel/runtime-corejs2
    3 依賴@babel/runtime-corejs3

    corejs2和corejs3還是有很大區別的。corejs2只轉換全局變量(Object)和靜態方法(Object.assign),并不轉換原型上的方法(Array.prototype.includes),corejs3會轉換原型上的方法。

    注意transform-runtime這個插件添加的polyfill都是私有的,不會影響到全局環境,而且還是按需引入,非常nice。

    小結:
    @babel/plugin-transform-runtime主要有三個作用:
    - 當使用 generators/async的時候自動引入 @babel/runtime/regenerator。
    - 為新特性的API添加實現。
    - 提取每個模塊內聯的helper們問引用。

    @babel/preset-env

    除了上面說的 @babel/plugin-transform-runtime插件,還想記錄下 @babel/preset-env關于polyfill的改變。

    這個preset在babel6的時候就承擔了很多功能,本文只記錄和polyfill相關的配置,useBuiltIns和 corejs。

    useBuiltIns

    在babel-preset-env的配置項中是一個boolean值,在@babel/preset-env的時候則擴展了幾個選項 "useage"和 "entry"。

    默認值是false,表示不會自動引入polyfills,并且不會處理 import “@babel/polyfill” 和 import “corejs”。

    注:babel7.4會放棄 @babel/polyfill,所以建議直接使用 corejs。

    entry

    在入口文件有 import "core-js/stable"和 import "regenerator-runtime/runtime"。
    會被自動分割為各個模塊的導入。

    require("core-js/modules/es.symbol");require("core-js/modules/es.symbol.description");require("core-js/modules/es.symbol.async-iterator");require("core-js/modules/es.symbol.has-instance");... ... ...require("core-js/modules/web.url-search-params");require("regenerator-runtime/runtime");

    只能在入口引入一次,多次會報錯。

    usage

    按需引入。同樣會造成全局污染。在我的理解中這個選項只是entry的一種增強,不需要在入口手動引入一次,并且可以按照使用特性多少按需引入。

    corejs

    值:2, 3 或者 { version: 2 | 3, proposals: boolean }, 默認是 2.

    這是新加的一個配置項。該選項只會在 useBuiltIns選項為 usage或者 entry并且 @babel/preset-env正確導入對應的corejs版本的情況下起作用。

    默認情況下只會注入穩定功能的 ECMAScript 特性。有三個特性可以修改:

    • 當時用配置 useBuiltIns: "entry"可以直接導入提案 import "core-js/proposals/string-replace-all"
    • 當時用 useBuiltIns: usage 的時候又有兩個可選:
      • 將shippedProposals(@babel/preset-env的另一個配置項)選項設置為true。這將啟用已在瀏覽器中提供一段時間的提議的polyfill和轉換。
      • 使用 corejs: {version:3,proposal:true}。這樣可以實現對core-js支持的每個提案的填充。

    babel6

    據我所知,在babel6中使用polyfill有四種方法:

  • 直接引入(影響全局,一勞永逸)

    在入口文件中 import 'babel-polyfill' / require('babel-polyfill')。使用webpack的話也可以在entry中添加 entry: ['babel-polyfill', 'src/index.js']。

    優點:
    一次引入,全局使用。
    會轉換實例方法和靜態方法,比較全面。

    缺點:
    影響全局作用域。
    打出來的包比較大,不管用沒用到都打進去了。

    使用場景:
    開發業務項目,比較全面,不會漏了從而出問題,比如Object.assign這樣的方法在ios8上面還是需要polyfill的。

  • 在babel-runtime中單獨引入

    和直接在入口引入polyfill不同,該插件引入的polyfill是模塊私有的。
    對于需要的polyfill需要手動引入,import Promise from 'babel-runtime/core-js/promise'

    優點:
    該模塊私有,不會影響到全局作用域。
    打出來的包因為按需引入包不會很大。

    缺點:
    因為不影響全局作用域,所以不會轉實例和靜態方法這樣的API。
    手動引入所需,搞不好會漏掉。

    使用場景:
    開發庫,框架之類可以使用,因為別人用你的東西然后不知情的情況下你改了別人的全局環境,然后出錯了就尷尬了。

  • 使用babel-plugin-transform-runtime按需引入

    這個插件可不簡單,有好幾個功能:

  • 和插件babel-runtime一樣引入的polyfill是私有的,不會影響全局作用域。并且是自動按需引入需要的polyfill,不需要想babel-runtime一樣一個一個手動引入。
  • 可以提取語法轉換時候每個模塊都生成的各種helper,成一個引用。
  • 自動轉換generators/async。
  • 優點:
    該模塊私有,不會影響到全局作用域。
    打出來的包因為按需引入包不會很大。
    自動按需引入,不需要手動,防止遺漏。
    提取helper,大大減少冗余代碼。

    缺點:
    因為不影響全局作用域,所以不會轉實例和靜態方法這樣的API。

    使用場景:
    同babel-runtime。

    注:該插件依賴babel-runtime。

  • 在babel-preset-env中設置配置項

  • {"presets": [["env", {"useBuiltIns": boolean}]] }

    useBuiltIns 選項是為了分割入口的 import 'babel-polyfill' / require(babel-polyfill)成按環境引入polyfill。該方式同第一中引入polyfill的方式,但是會按照配置的環境去按需引入,稍微好點。

    小結:
    1. babel6的核心有 babel-core babel-cli babel-node babel-register babel-polyfill,這些在babel7會有所修改。
    2. polyfill 是依賴core-js的
    3. babel7.4放棄了@babel/polyfill直接依賴core-js@2或者3。

    babel-plugin-transform-runtime的配置項

    {"helpers": false, // defaults to true"polyfill": false, // defaults to true"regenerator": true, // defaults to true"moduleName": "babel-runtime" // defaults to "babel-runtime" }

    對于polyfill的自動處理和helper的提取都是依賴babel-runtime完成的,所以該插件依賴babel-runtime。

    polyfill例子

    input:

    var promise = new Promise;

    output:

    var _promise = require("babel-runtime/core-js/promise"); // 注意這里,根本是從core-js里面引入的var _promise2 = _interopRequireDefault(_promise);function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }var promise = new _promise2.default();

    helper的例子:

    input:

    class Person {}

    usually turns into:

    "use strict";// 這就是helper函數,每個模塊都會被實現一遍,十分浪費,冗余。 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }var Person = function Person() {_classCallCheck(this, Person); };

    通過runtime轉一下:

    "use strict";var _classCallCheck2 = require("babel-runtime/helpers/classCallCheck"); // 從runtime中引入,沒有再實現一遍var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }var Person = function Person() {(0, _classCallCheck3.default)(this, Person); };

    generator同樣是 require("babel-runtime/regenerator");引入的。

    參考

    babel官網@babel/plugin-transform-runtime
    npm->babel-plugin-transform-runtime
    babel到底該如何配置?
    babel手冊
    Babel是一個JavaScript編譯器
    babel7簡單升級

    總結

    以上是生活随笔為你收集整理的babel6和babel7中关于polyfill和preset-env和babel-plugin-transform-runtime等总结的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。