webpack进阶知识之babel-polyfill和babel-runtime的区别

1. 在开始本章节前先学习一下必备前置知识

  1. babel-loader:每一个浏览器对js语法兼容性不同,为了使浏览器对js的解析尽量保持一致,所以就出现了Babel。Babel把ECMAScript 2015+代码进行降级,用级别低兼容性好的语法重新实现一遍高级语法。
  2. @babel/polyfill:Babel默认只转换新的Javascript语法,而不转换新的API,它是通过向全局对象和内置对象的prototype上添加方法来实现的。比如运行环境中不支持Array.prototype.find方法,引入polyfill, 我们就可以使用ES6方法来编写了。注:Babel 7.4之后不再推荐使用@babel/polyfill(全局污染问题)
  3. @babel/preset-env: 默认只支持语法转化,需要开启useBuiltIns配置才能转化API和实例方法
  4. babel-runtime: Babel为了解决全局空间污染的问题,提供了单独的包babel-runtime用以提供编译模块的工具函数。简单说 babel-runtime 更像是一种按需加载的实现。比如你哪里需要使用 Promise,只要在这个文件头部import Promise from 'babel-runtime/core-js/promise'就行了
  5. babel-plugin-transform-runtime:为了解决
    • 多个文件重复引用 相同helpers(帮助函数)=>提取运行时
    • 新API方法全局污染 -> 局部引入

2. 安装依赖

pnpm add @babel/polyfill @babel/preset-env babel-loader core-js@2 core-js@3 babel-runtime @babel/plugin-transform-runtime @babel/runtime-corejs3 -D

3. webpack中使用@babel/polyfill

  1. useBuiltIns: false
    • 表示不对polyfills 处理,此时不对 polyfill 做操作。如果引入 @babel/polyfill,则无视配置的浏览器兼容,引入所有的 polyfill
{





    test: /\.js?$/, // 匹配后缀为js的文件
    exclude: /node_modules/, // 忽略需要操作的文件
    use: {

        loader: 'babel-loader',

        options: {

            targets: {
                "browsers": ["ie >= 8", "chrome >= 62"], // 表示我们需要支持哪些平台和哪些版本
            },
            presets: [["@babel/preset-env", { useBuiltIns: false }]]
        }
    }
}

// js编译后

import '@babel/polyfill';
let sum = (a, b) => a + b;
let promise = Promise.resolve();
console.log([1, 2, 3].find(item => item === 2));
  1. useBuiltIns: entry
    • 根据配置的浏览器兼容,引入浏览器需要兼容处理的 polyfill,不能实现按需加载。
    • corejs默认是2,如果配置 corejs: 3, 则import '@babel/polyfill' 需要改成 import 'core-js/stable';import 'regenerator-runtime/runtime';
{





  test: /\.js?$/,


  exclude: /node_modules/,


  use: {


      loader: 'babel-loader',


      options: {


         presets: [["@babel/preset-env", { useBuiltIns: 'entry', corejs: { version: 3 } }]]
      }

  }

}


// core-js@2

import '@babel/polyfill';
let sum = (a, b) => a + b;
let promise = Promise.resolve();
console.log([1, 2, 3].find(item => item === 2));

// core-js@3

import 'core-js/stable';
import 'regenerator-runtime/runtime';
let sum = (a, b) => a + b;
let promise = Promise.resolve();
console.log([1, 2, 3].find(item => item === 2));
  1. useBuiltIns: usage
    • 会根据配置的浏览器兼容,以及你代码中用到的 API 来进行 polyfill,实现了按需添加
{





  test: /\.js?$/,


  exclude: /node_modules/,


  use: {


      loader: 'babel-loader',


      options: {


         presets: [["@babel/preset-env", { useBuiltIns: 'usage', corejs: { version: 3 } }]]

      }

  }

}

4. webpack中使用babel-plugin-transform-runtime

  1. 启用插件babel-plugin-transform-runtime后,Babel就会使用babel-runtime下的工具函数
  2. babel-plugin-transform-runtime插件能够将这些工具函数的代码转换成require语句,指向为对babel-runtime的引用
  3. babel-plugin-transform-runtime就是可以在我们使用新 API 时自动 import babel-runtime里面的polyfill
    • 当我们使用 async/await 时,自动引入 babel-runtime/regenerator
    • 当我们使用 ES6 的静态事件或内置对象时,自动引入 babel-runtime/core-js
    • 移除内联babel helpers并替换使用babel-runtime/helpers 来替换
{





    test: /\.js?$/,
    exclude: /node_modules/,
    use: {

        loader: 'babel-loader',

        options: {

            sourceType: "unambiguous", // Babel 会根据文件上下文推断使用esm语法还是common语法
            presets: [["@babel/preset-env", { useBuiltIns: 'usage', corejs: { version: 3 } }]],
            plugins: [
                [
                    "@babel/plugin-transform-runtime",
                    {
                        corejs: 3, // 当我们使用 ES6 的静态事件或内置对象时自动引入 babel-runtime/core-js
                        helpers: true,// 避免内联的 helper 代码在多个文件重复出现,使用babel-runtime/helpers 来替换
                        regenerator: true // 转换成使用regenerator runtime来避免污染全局域
                    }
                ],
            ]
        }
    }
 }

// 转换

// corejs: 3
//var _Promise = __webpack_require__("./node_modules/@babel/runtime-corejs3/core-js-stable/promise.js");
const p = new Promise(() => { });

// regenerator: true
//var _regeneratorRuntime = __webpack_require__(/*! @babel/runtime-corejs3/regenerator */ "./node_modules/@babel/runtime-corejs3/regenerator/index.js");
function* gen() {}

5.最佳实践

  1. 项目开发
    • plugin-transform-runtime只使用其移除内联复用的辅助函数的特性,减小打包体积
{





  test: /\.js?$/,


  exclude: /node_modules/,


  use: {


      loader: 'babel-loader',


      options: {


         presets: [["@babel/preset-env", { useBuiltIns: 'usage', corejs: { version: 3 } }]]

         plugins: [["@babel/plugin-transform-runtime", { "corejs": false }]]
      }
  }
}
  1. 类库开发
    • 类库开发尽量不使用污染全局环境的polyfill,因此@babel/preset-env只发挥语法转换的功能
    • polyfill由@babel/plugin-transform-runtime来处理,推荐使用core-js@3
{





     presets: [["@babel/preset-env"]],
     plugins: [["@babel/plugin-transform-runtime", corejs: { version: 3 } }]]
}

© 版权声明
THE END
喜欢就支持一下吧
点赞0

Warning: mysqli_query(): (HY000/3): Error writing file '/tmp/MYXtZHE7' (Errcode: 28 - No space left on device) in /www/wwwroot/583.cn/wp-includes/class-wpdb.php on line 2345
admin的头像-五八三
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

图形验证码
取消
昵称代码图片