美文网首页webpackReact
babel-runtime和babel-polyfill的作用介

babel-runtime和babel-polyfill的作用介

作者: zackxizi | 来源:发表于2018-04-10 17:01 被阅读40次

    Babel编译转码的范围

    Babel默认只转换新的JavaScript语法,而不转换新的API。 例如,Iterator、Generator、Set、Maps、Proxy、Reflect、Symbol、Promise 等全局对象,以及一些定义在全局对象上的方法(比如 Object.assign)都不会转译。 如果想使用这些新的对象和方法,则需要为当前环境提供一个polyfill

    babel-polyfill

    目前最常用的配合Babel一起使用的polyfill是babel-polyfill,它会”加载整个polyfill库”,针对编译的代码中新的API进行处理,并且在代码中插入一些帮助函数。

    比如说:代码中包含

    const key = 'babel'
    const obj = {
        [key]: 'polyfill',
    }
    

    使用babel-polyfill配合转码后,代码会变成这样

    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 key = 'babel';
    var obj = _defineProperty({}, key, Object.assign({}, { key: 'polyfill' }));
    

    babel-runtime

    babel-polyfill解决了Babel不转换新API的问题,但是直接在代码中插入帮助函数,会导致污染了全局环境,并且不同的代码文件中包含重复的代码,导致编译后的代码体积变大。 (比如:上述的帮助函数_defineProperty有可能在很多的代码模块文件中都会被插入)

    Babel为了解决这个问题,提供了单独的包babel-runtime用以提供编译模块的工具函数, 启用插件babel-plugin-transform-runtime后,Babel就会使用babel-runtime下的工具函数,上述的代码就会变成这样

    var _defineProperty2 = __webpack_require__("./node_modules/babel-runtime/helpers/defineProperty.js");
    
    var _defineProperty3 = _interopRequireDefault(_defineProperty2);
    
    var _assign = __webpack_require__("./node_modules/babel-runtime/core-js/object/assign.js");
    
    var _assign2 = _interopRequireDefault(_assign);
    
    function _interopRequireDefault(obj) { 
        return obj && obj.__esModule ? obj : { default: obj }; 
    }
    
    var key = 'babel';
    var obj = (0, _defineProperty3.default)(
                {}, key, (0, _assign2.default)({}, { key: 'polyfill' })
              );
    
    

    可以看到上述转换后的代码中_defineProperty帮助函数是通过babel-runtime下的模块引用的, 同时Object.assign也变成了模块引用, 这样可以避免自行引入polyfill时导致的污染全局命名空间的问题。

    配置

    使用babel-polyfill需要额外安装babel-polyfill依赖包, 然后在webpack配置文件中的入口或者公共模块中加入’babel-polyfill’即可,代码如下:

    entry: {
        common: [
            `babel-polyfill`,
            `whatwg-fetch`,
            `react`,
            `react-dom`,
            `redux`,
            `react-redux`,
            `js-cookie`,
        ],
    },
    

    使用babel-runtime需要额外安装babel-runtime和babel-plugin-transform-runtime依赖包, 然后在.babelrc配置文件中启用transform-runtime, 代码如下:

    {
        "presets": [
            "es2015",
            "react",
            "stage-0"
        ],
        "plugins": [
            "transform-runtime"
        ]
    }
    
    

    比较

    babel-polyfill与babel-runtime相比虽然有各种缺点,但在某些情况下仍然不能被babel-runtime替代, 例如,代码:[1, 2, 3].includes(3),Object.assign({}, {key: 'value'}),Array,Object以及其他”实例”下es6的方法,babel-runtime是无法支持的, 因为babel-runtime只支持到static的方法。

    结论

    babel-runtime适合在组件,类库项目中使用,而babel-polyfill适合在业务项目中使用。
    参考:https://stackoverflow.com/questions/31781756/is-there-any-practical-difference-between-using-babel-runtime-and-the-babel-poly

    vue-cli脚手架中使用

    babel-polyfill

    在main.js中引用babel-polyfill

    import 'babel-polyfill'
    

    bable-runtime

    在.babelrc文件中使用

    {
      "presets": [
        ["env", {
          "modules": false,
          "targets": {
            "browsers": ["> 1%", "last 2 versions", "not ie <= 8"]
          }
        }],
        "stage-2"
      ],
      "plugins": ["transform-vue-jsx", "transform-runtime"],
      "env": {
        "test": {
          "presets": ["env", "stage-2"],
          "plugins": ["transform-vue-jsx", "transform-es2015-modules-commonjs", "dynamic-import-node"]
        }
      }
    }
    

    相关文章

      网友评论

        本文标题:babel-runtime和babel-polyfill的作用介

        本文链接:https://www.haomeiwen.com/subject/xtynhftx.html