轉義babel的polyfill和runtime的區別


babel-polyfill 使用場景

Babel 默認只轉換新的 JavaScript 語法,而不轉換新的 API。例如,Iterator、Generator、Set、Maps、Proxy、Reflect、Symbol、Promise 等全局對象,以及一些定義在全局對象上的方法(比如 Object.assign)都不會轉譯。如果想使用這些新的對象和方法,必須使用 babel-polyfill,為當前環境提供一個墊片。

babel-runtime 使用場景

Babel 轉譯后的代碼要實現源代碼同樣的功能需要借助一些幫助函數,例如,{ [name]: 'JavaScript' } 轉譯后的代碼如下所示:

'use strict'; function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } var obj = _defineProperty({}, 'name', 'JavaScript');

類似上面的幫助函數 _defineProperty 可能會重復出現在一些模塊里,導致編譯后的代碼體積變大。Babel 為了解決這個問題,提供了單獨的包 babel-runtime 供編譯模塊復用工具函數。

啟用插件 babel-plugin-transform-runtime 后,Babel 就會使用 babel-runtime 下的工具函數,轉譯代碼如下:

'use strict'; // 之前的 _defineProperty 函數已經作為公共模塊 `babel-runtime/helpers/defineProperty` 使用 var _defineProperty2 = require('babel-runtime/helpers/defineProperty'); var _defineProperty3 = _interopRequireDefault(_defineProperty2); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } var obj = (0, _defineProperty3.default)({}, 'name', 'JavaScript');

除此之外,babel 還為源代碼的非實例方法(Object.assign,實例方法是類似這樣的 "foobar".includes("foo"))和 babel-runtime/helps 下的工具函數自動引用了 polyfill。這樣可以避免污染全局命名空間,非常適合於 JavaScript 庫和工具包的實現。例如 const obj = {}, Object.assign(obj, { age: 30 }); 轉譯后的代碼如下所示:

'use strict'; // 使用了 core-js 提供的 assign var _assign = require('babel-runtime/core-js/object/assign'); var _assign2 = _interopRequireDefault(_assign); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } var obj = {}; (0, _assign2.default)(obj, { age: 30 });

思考:babel-runtime 為什么適合 JavaScript 庫和工具包的實現?

  1. 避免 babel 編譯的工具函數在每個模塊里重復出現,減小庫和工具包的體積;

  2. 在沒有使用 babel-runtime 之前,庫和工具包一般不會直接引入 polyfill。否則像 Promise 這樣的全局對象會污染全局命名空間,這就要求庫的使用者自己提供 polyfill。這些 polyfill 一般在庫和工具的使用說明中會提到,比如很多庫都會有要求提供 es5 的 polyfill。在使用 babel-runtime 后,庫和工具只要在 package.json 中增加依賴 babel-runtime,交給 babel-runtime 去引入 polyfill 就行了;

總結:

  1. 具體項目還是需要使用 babel-polyfill,只使用 babel-runtime 的話,實例方法不能正常工作(例如 "foobar".includes("foo"));

  2. JavaScript 庫和工具可以使用 babel-runtime,在實際項目中使用這些庫和工具,需要該項目本身提供 polyfill;


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM