babel-runtime 如何缩小打包体积

在这里插入图片描述

🤖 作者简介:水煮白菜王,一位前端劝退师 👻
👀 文章专栏: 前端专栏 ,记录一下平时在博客写作中,总结出的一些开发技巧和知识归纳总结✍。
感谢支持💕💕💕

目录

    • @babel/preset-env
    • @babel/polyfill
    • babel-runtime
      • 主要功能
      • 补充
    • babel-plugin-transform-runtime
      • 配置
    • 示例
      • 控制引入 babel-runtime
      • 控制 corejs 配置

在前端工程化领域,包体积优化一直是一个备受关注的话题。随着项目规模扩大和功能迭代,打包后的文件体积逐渐膨胀。而对于网页加载速度和性能优化来说,减小打包体积是至关重要的一环。
为此,在这篇文章中,将探讨如何利用 babel-runtime 这一工具来帮助我们将重复的定义通过模块导入的方式引入,缩减打包体积以提升项目性能。

Babel 是一个被广泛使用的 JS 编译器,用于将新语法转换为向后兼容的 JS 代码。一般情况下,我们可以通过安装预设和插件控制 ****Babel 的代码转译,比如:
预设(Presets 一组预定义的转换规则的集合)

  1. @babel/preset-env:这是 Babel 官方推荐的预设之一,用于根据目标环境自动确定所需的转换和 polyfill。
  2. @babel/preset-react:用于支持 React 项目中的 JSX 和其他相关特性的预设。·
  3. @babel/preset-typescript:用于支持 TS 项目中的预设,能够将 TS 代码转换为 JS 代码。

插件(Plugins 单个转换规则的集合)
4. @babel/plugin-proposal-class-properties:用于支持 JS 类的属性初始化器,包括静态属性和实例属性。
5. @babel/plugin-transform-arrow-functions:将箭头函数转换为普通函数表达式,以提供更广泛的兼容性。
6. @babel/plugin-transform-runtime:将 Babel 编译时注入的辅助函数转换为引用运行时公共函数的方式,以减小输出文件的体积。

@babel/preset-env

@babel/preset-env 的主要功能包括:

  • 自动 polyfill:根据目标环境自动导入所需的 polyfill,从而实现对新特性的兼容性支持。

  • 智能转换:基于目标环境的浏览器或 Node 版本来自动转换 ES6+ 语法或 API。

  • 模块转换:支持将模块转换为不同类型(CommonJS、AMD、UMD 等)的模块系统。

  • 按需加载:支持根据需要选择和加载特定的转换规则或插件。

使用 @babel/preset-env 的方式也非常简单,只需要在 .babelrc 或 babel.config.js 中配置该预设即可,下面是一个综合案例:

{"presets": [["@babel/preset-env",{// 目标环境设置为最近的两个浏览器版本以及 Safari 7 及以上版本"targets": {"browsers": ["last 2 versions", "safari >= 7"]},// 将 ES6 模块转换为 CommonJS 模块"modules": "commonjs",// 启用按需加载 polyfill 的功能"useBuiltIns": "usage",// 使用 core-js 3 版本的 polyfill"corejs": 3,// 打印详细的调试信息"debug": true}]]
}

注意:useBuiltIns 控制了 polyfill 的导入方式,用来配合 @babel/polyfill 使用,值得注意的是,官方不再推荐 Babel > 7.4.0 时使用 @babel/polyfill,可以选择使用 core-js。
更多配置规则请参考:https://babeljs.io/docs/babel-preset-env

@babel/polyfill

从 Babel 7.4.0 开始,这个包已经被弃用,取而代之的是直接包含 core-js/stable
在本地 node_module 中,可以看到 @babel/polyfill 的依赖包含了 core-js 和 regenerator-runtime,可以认为 polyfill 本身就是 core-js + regenerator-runtime。

在这里插入图片描述
在这里插入图片描述
从 Babel 7.4.0 开始,我们需要用 core-js 替代 babel-polyfill,而 regenerator-runtime 会在安装 @babel/runtime 时被依赖安装,因此不用额外安装。

babel-runtime

babel-runtime 是一个由 Babel 提供的运行时库,它包括了一些在编译过程中需要用到的辅助函数和类,例如 ES6/ES7 语法的 polyfill、generator 函数的处理、Promise 的实现等。

主要功能

babel-runtime 的实现主要功能有两点:

  1. 将转译中需要的helper 函数从一个模块中引入,避免重复定义、减小打包体积

下面是一些常见的辅助函数和类的实现:

  • classCallCheck:用于实现 ES6 类的构造函数中的类检查。它会检查是否使用 new 关键字来调用类,并在没有正确调用的情况下抛出错误。
  • defineEnumerableProperties:用于定义对象的可枚举属性。它接受一个对象和一组属性描述符,并将这些属性添加到对象中,并确保它们是可枚举的。
  • extends:用于实现 ES6 类继承的辅助函数。它会创建一个新的子类,并确保正确设置原型链和构造函数。
  • asyncToGenerator:用于将 generator 函数转换为基于 Promise 的异步函数的辅助函数。它接受一个 generator 函数并返回一个新的函数,该函数可以像普通的异步函数一样被调用。
  • regeneratorRuntime:用于支持 generator 函数的运行时库。它提供了 generator 函数所需的运行时环境,包括状态机、迭代器和 Promise 的支持。
  1. 开发类库/工具时,避免生产污染全局空间的方法。

在一个项目中,我们定义了一个 Array 原型链上的方法(比如 Array.includes()),项目依赖 babel-polyfill 实现转译。此时,项目引入一个依赖,调用的方法需要使用 Array.includes(),那么在打包时,由于 polyfill 导入于全局环境,就会出现冲突,导致出错。
解决方案就是用 babel-runtime 处理全局内置对象,将其模块化,并通过模块导入的方式引入。

补充

然而 @babel/runtime 没有支持实例方法,只能通过配置 corejs ,使用 babel/runtime-corejs@x
控制相关 polyfill 的引入,然而 core-js2 的 polyfill 覆盖范围相对较小,以下陈列了相关包的区别:

  • @babel/polyfill:core-js + regenerator-runtime,Babel 7.4.0后弃用。
  • @babel/runtime:Babel 默认的运行时依赖模块,提供相关 helpers 函数和regenerator-runtime,不包含任何 polyfill 功能。
  • @babel/runtime-corejs2:基于 @babel/runtime ,提供了 core-js2 支持部分 polyfill。
  • @babel/runtime-corejs3:基于 @babel/runtime ,提供了 core-js3 支持更广泛的 polyfill。

babel-plugin-transform-runtime

需要注意的是,babel-runtime 只是一个工具库,需要和 babel-plugin-transform-runtime 配合使用。
babel-plugin-transform-runtime 可以让 Babel 在编译过程中, 引用模块 @babel/runtime提供一些辅助函数和类 ,从而避免在编译后的代码中重复出现相同的代码。

配置

首先,安装相关包。

npm install --save-dev @babel-plugin-transform-runtime
npm install --save @babel-runtime

其次在 .babelrc 或 babel.config.js 中配置 @babel/plugin-transform-runtime ****插件,corejs 配置项控制是否引入 core-js 或 core-js 的版本。

{"presets": [["@babel/preset-env"],],"plugins": [["@babel/plugin-transform-runtime", {"corejs": false // 可选 false | 2 | 3}]]
}
名称类型作用使用场景
@babel/preset-envpreset根据目标环境自动确定需要的转换规则和 polyfill现代 JS 代码转换兼容老版本浏览器/环境
@babel/polyfill (已废弃)polyfill提供完整的 ES6+ 环境补丁 (包含 core-js 和 regenerator-runtime)全局注入 polyfill (Babel 7.4+ 推荐直接使用 core-js 和 regenerator-runtime)
babel-runtime (旧版本)运行时依赖提供编译时的工具函数和 regenerator-runtime配合 transform-runtime 插件减少代码重复 (已被 @babel/runtime 取代)
babel-plugin-transform-runtime插件自动替换 helper 函数为 runtime 引用,并可配置 core-js 按需 polyfill开发库时避免污染全局环境,减少代码体积

接下来我们可以通过观察不同 corejs 配置和是否引入 babel-runtime 打包的结果理解一下作用。

示例

控制引入 babel-runtime

转译代码:

class Animal {}

接下来我们通过修改是否启用 babel-plugin-transform-runtime 控制 babel-runtime 的引入:

// 不引入 babel-runtime
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
var Animal = /*#__PURE__*/_createClass(function Animal() {_classCallCheck(this, Animal);
});// 引入 babel-runtime,corejs:false
/* harmony import */ var _babel_runtime_helpers_createClass__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @babel/runtime/helpers/createClass */ "./node_modules/.pnpm/@babel+runtime@7.23.9/node_modules/@babel/runtime/helpers/esm/createClass.js");
/* harmony import */ var _babel_runtime_helpers_classCallCheck__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @babel/runtime/helpers/classCallCheck */ "./node_modules/.pnpm/@babel+runtime@7.23.9/node_modules/@babel/runtime/helpers/esm/classCallCheck.js");var Animal = /*#__PURE__*/(0,_babel_runtime_helpers_createClass__WEBPACK_IMPORTED_MODULE_0__["default"])(function Animal() {(0,_babel_runtime_helpers_classCallCheck__WEBPACK_IMPORTED_MODULE_1__["default"])(this, Animal);
});

可以看到 babel-runtime 是通过引入模块实现 class 的,避免了多文件时定义了多个工具函数,有效减少了打包体积。

控制 corejs 配置

转译代码

new Promise();
string.trimStart()

为体现 corejs 的差异,我们使用两种实例方法 Promise、String.trimStart() 进行对比。

// corejs:false
new Promise();
string.trimStart();// corejs:2
/* harmony import */ var _babel_runtime_corejs2_core_js_promise__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @babel/runtime-corejs2/core-js/promise */ "./node_modules/.pnpm/@babel+runtime-corejs2@7.23.9/node_modules/@babel/runtime-corejs2/core-js/promise.js");
/* harmony import */ var _babel_runtime_corejs2_core_js_promise__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_babel_runtime_corejs2_core_js_promise__WEBPACK_IMPORTED_MODULE_0__);new (_babel_runtime_corejs2_core_js_promise__WEBPACK_IMPORTED_MODULE_0___default())();
string.trimStart();// corejs:3
/* harmony import */ var _babel_runtime_corejs3_core_js_stable_promise__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @babel/runtime-corejs3/core-js-stable/promise */ "./node_modules/.pnpm/@babel+runtime-corejs3@7.23.9/node_modules/@babel/runtime-corejs3/core-js-stable/promise.js");
/* harmony import */ var _babel_runtime_corejs3_core_js_stable_promise__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_babel_runtime_corejs3_core_js_stable_promise__WEBPACK_IMPORTED_MODULE_0__);
/* harmony import */ var _babel_runtime_corejs3_core_js_stable_instance_trim_start__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @babel/runtime-corejs3/core-js-stable/instance/trim-start */ "./node_modules/.pnpm/@babel+runtime-corejs3@7.23.9/node_modules/@babel/runtime-corejs3/core-js-stable/instance/trim-start.js");
/* harmony import */ var _babel_runtime_corejs3_core_js_stable_instance_trim_start__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_babel_runtime_corejs3_core_js_stable_instance_trim_start__WEBPACK_IMPORTED_MODULE_1__);new (_babel_runtime_corejs3_core_js_stable_promise__WEBPACK_IMPORTED_MODULE_0___default())();
_babel_runtime_corejs3_core_js_stable_instance_trim_start__WEBPACK_IMPORTED_MODULE_1___default()(string).call(string);

依据结果可以看出,
corejs: false 只对ES语法进行了转换。
corejs:2 为我们的代码创建了一个沙盒环境,避免了全局空间污染。
corejs: 3 在 corejs: 2的基础上加入了新的 polyfill 以处理更多的实例方法。
由此总结,对于 Babel < 7.4.0 时,类库/工具项目应选择 @babel/runtime,其他项目选择 @babel/polyfill,当 Babel >= 7.4.0 时,一律使用 @babel/runtime。

在这里插入图片描述
如果你觉得这篇文章对你有帮助,请点赞 👍、收藏 👏 并关注我!👀
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/77003.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

剑指Offer(数据结构与算法面试题精讲)C++版——day7

剑指Offer&#xff08;数据结构与算法面试题精讲&#xff09;C版——day7 题目一&#xff1a;最多删除一个字符得到回文题目二&#xff1a;回文子字符串的个数题目三&#xff1a;删除倒数第k个节点 题目一&#xff1a;最多删除一个字符得到回文 这里我们可以在经典的字符串回文…

2025年常见渗透测试面试题(题目+回答)

网络安全领域各种资源&#xff0c;学习文档&#xff0c;以及工具分享、前沿信息分享、POC、EXP分享。不定期分享各种好玩的项目及好用的工具&#xff0c;欢迎关注。 目录 常见面试题 一、渗透测试经历与技术复盘 二、高频漏洞类型与攻防体系 三、渗透工具链与技术特性 四、…

大数据与人工智能之大数据架构(Hadoop、Spark、Flink)

一、核心特性与架构设计 1. Hadoop&#xff1a;分布式批处理的基石 核心组件&#xff1a; HDFS&#xff1a;分布式文件系统&#xff0c;支持大规模数据存储。MapReduce&#xff1a;基于“分而治之”的批处理模型&#xff0c;适合离线分析。 架构特点&#xff1a; 批处理主导&…

从IoT到AIoT:智能边界的拓展与AI未来趋势预测

文章目录 引言&#xff1a;从连接万物到感知万物1. AIoT的本质&#xff1a;将智能嵌入万物2. AIoT的推动力量与挑战2.1 推动力量2.2 关键挑战 3. 五大AIoT未来趋势预测趋势一&#xff1a;边缘智能将成为主流架构趋势二&#xff1a;AI模型将向自适应与多任务演进趋势三&#xff…

从本地新建文件夹到拉取远程仓库 dev 分支的完整步骤

《从本地新建文件夹到拉取远程仓库 dev 分支的完整步骤》 下面为你详细介绍从本地新建文件夹开始&#xff0c;将远程仓库的 dev 分支拉取到本地的具体步骤&#xff1a; 1. 创建新文件夹 在本地电脑上新建一个文件夹&#xff0c;作为存放项目代码的目录。你可以通过图形界面操…

python/pytorch杂聊

Dataset 是否需要自己定义&#xff1a;如果你使用的数据集不是 PyTorch 提供的标准数据集&#xff08;如 MNIST、CIFAR-10 等&#xff09;&#xff0c;那么你需要继承 torch.utils.data.Dataset 类并实现两个方法&#xff1a;__len__() 和 __getitem__()。__len__() 应该返回数…

PHP 安全 E-mail

PHP 安全 E-mail 引言 随着互联网的普及和电子商务的发展,电子邮件成为了人们日常生活中不可或缺的通信工具。PHP作为一种广泛使用的服务器端脚本语言,也经常被用于发送和接收电子邮件。然而,在PHP中处理电子邮件时,安全性问题不容忽视。本文将深入探讨PHP安全发送电子邮…

【夜话系列】DelayQueue延迟队列(下):实战应用与面试精讲

🔥 本文是DelayQueue系列的下篇,聚焦实战应用场景和性能优化。通过多个真实案例,带你掌握DelayQueue在项目中的最佳实践和性能调优技巧。 📚 系列专栏推荐: JAVA集合专栏 【夜话集】JVM知识专栏数据库sql理论与实战小游戏开发文章目录 一、DelayQueue实战应用1.1 订单超…

Redis(笔记)

简介&#xff1a; 常用数据类型: 常用操作命令&#xff1a; Redis的Java客户端&#xff1a; 操作字符串类型的数据&#xff1a; 操作Hash类型的数据&#xff1a; 操作列表类型的数据&#xff1a; 操作集合类型的数据&#xff1a; 操作有序集合类型数据&#xff1a; 通用命令…

PhotoShop学习05

1.选区基础知识 选区&#xff0c;就是选定一些区域&#xff0c;我们对图片的更改只在选区内生效&#xff0c;这样可以精细调整图片的部分而不会影响整体。它的快捷键是M。 我们用点击鼠标后滑动就会出现虚线框&#xff0c;虚线框内的就是我们选定的区域。这时我们再滑动就会创…

使用Redission实现分布式锁

分布式锁在分布式系统中非常重要&#xff0c;主要用于解决多个进程/服务并发访问共享资源时的数据一致性问题。在日常开发中常用于&#xff1a; 1. 防止重复操作&#xff08;幂等性控制&#xff09; 场景&#xff1a;用户重复提交订单、重复支付、重复点击等。 示例&#xff1…

VScode 画时序图(FPGA)

1、先安装插件&#xff1a; 2、然后就可以编写一个.js文件&#xff0c;如下&#xff1a; {signal: [{name: clk, wave: p.......|..},{name: rstn, wave: 01......|..},{name: din_vld, wave: 0.1.0...|..},{name: din, wave: "x.x...|..", data: ["D0", …

嵌入式学习笔记——I2C

IIC协议详解 一、IIC协议简介二、IIC总线结构图三、IIC通信流程详解1. 空闲状态 : 双高空闲2. 起始信号&#xff08;START&#xff09;: 时高数下开始3. 停止信号&#xff08;STOP&#xff09;: 时高数上结束4. 数据传输格式 : 时高数稳&#xff0c;时低数变5. 应答信号 四、写…

Apifox Helper 与 Swagger3 区别

核心定位差异 Apifox Helper 定位&#xff1a;基于 IDEA 的代码注释解析工具&#xff0c;与 Apifox 平台深度集成&#xff0c;实现文档自动生成接口管理测试协作的一体化流程。 特点&#xff1a; 通过解析 Javadoc、KDoc 等注释生成文档&#xff0c;代码零侵入&#xff08;无…

单片机实现多线程的方法汇总

在单片机上实现“多线程”的方法有几种&#xff0c;下面按照从简单到复杂、从轻量到系统性来列出常见的方案&#xff1a; &#x1f9f5; 一、伪多线程&#xff08;最轻量&#xff09; 方法&#xff1a;主循环 状态机 / 定时器轮询 主循环中轮流调用各个任务的处理函数&#x…

网络:华为数通HCIA学习:静态路由基础

文章目录 前言静态路由基础静态路由应用场景 静态路由配置静态路由在串行网络的配置静态路由在以太网中的配置 负载分担配置验证 路由备份&#xff08;浮动静态路由&#xff09;配置验证 缺省路由配置验证 总结 华为HCIA 基础实验&#xff0d;静态路由 & eNSP静态路由 基础…

[项目总结] 在线OJ刷题系统项目技术应用(下)

&#x1f338;个人主页:https://blog.csdn.net/2301_80050796?spm1000.2115.3001.5343 &#x1f3f5;️热门专栏: &#x1f9ca; Java基本语法(97平均质量分)https://blog.csdn.net/2301_80050796/category_12615970.html?spm1001.2014.3001.5482 &#x1f355; Collection与…

Qt音频输出:QAudioOutput详解与示例

1. 简介 QAudioOutput是Qt多媒体框架中的一个关键类&#xff0c;它提供了将PCM&#xff08;脉冲编码调制&#xff09;原始音频数据发送到音频输出设备的接口。作为Qt多媒体组件的一部分&#xff0c;QAudioOutput允许开发者在应用程序中实现音频播放功能&#xff0c;支持多种音…

【计算机网络】Linux配置SNAT/DNAT策略

什么是NAT&#xff1f; NAT 全称是 Network Address Translation&#xff08;网络地址转换&#xff09;&#xff0c;是一个用来在多个设备共享一个公网 IP上网的技术。 NAT 的核心作用&#xff1a;将一个网络中的私有 IP 地址&#xff0c;转换为公网 IP 地址&#xff0c;从而…

Redis淘汰策略详解!

目录 一、为什么需要淘汰策略&#xff1f; &#x1f914;二、Redis 的淘汰策略详解 &#x1f447;三、如何选择合适的淘汰策略&#xff1f; &#x1f914;➡️✅四、如何切换 Redis 的淘汰策略&#xff1f; ⚙️&#x1f527;五、总结 &#x1f389; &#x1f31f;我的其他文章…