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 庫和工具包的實現?
-
避免 babel 編譯的工具函數在每個模塊里重復出現,減小庫和工具包的體積;
-
在沒有使用 babel-runtime 之前,庫和工具包一般不會直接引入 polyfill。否則像 Promise 這樣的全局對象會污染全局命名空間,這就要求庫的使用者自己提供 polyfill。這些 polyfill 一般在庫和工具的使用說明中會提到,比如很多庫都會有要求提供 es5 的 polyfill。在使用 babel-runtime 后,庫和工具只要在 package.json 中增加依賴 babel-runtime,交給 babel-runtime 去引入 polyfill 就行了;
總結:
-
具體項目還是需要使用 babel-polyfill,只使用 babel-runtime 的話,實例方法不能正常工作(例如
"foobar".includes("foo")
); -
JavaScript 庫和工具可以使用 babel-runtime,在實際項目中使用這些庫和工具,需要該項目本身提供 polyfill;
疑問:像 antd@2.x 這樣的庫使用了 babel-runtime,在實際項目中使用 antd@2.x,我們需要引入 babel-polyfill。但全部 polyfill 打包壓縮下來也有 80kb 左右,其中很多 polyfill 是沒有用到的,如何減少體積呢?手工一個個引入使用到的 polyfill,似乎維護成本太高!
歡迎大家加入前端交流群一起討論:498524034