axios二次封装和请求发送

本文介绍了如何使用Babel解决JavaScript兼容性问题,包括babel编译流程、主要依赖库的介绍,以及@babel/polyfill和@babel/plugin-transform-runtime的使用。通过实例演示了如何配置和使用Babel实现ES6到低版本JS的转换,以确保在不同环境下运行。最后讨论了在开发第三方依赖包时如何选择合适的Babel插件。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

随着ES6以及后面版本的问世,确实给前端JavaScript增添了不少活力,层出不穷的高级语法不仅提升编码效率,还使得前端的编码风格越来越靠近贴近主流。然而这些高级语法在有些浏览器上却运行不了,是因为浏览器还没法编译js的高级语法导致出现兼容性问题,需要将这些高级语法编译成浏览器能够运行的低版本语法。今天讲解的babel就是来解决这个js兼容问题的。

Babel,又名Babel.js。 是一个用于web 开发,且自由开源的JavaScript 编译器、转译器。 Babel 使软件开发者能够以偏好的编程语言或风格来写作源代码,并将其利用Babel 翻译成JavaScript。 Babel 是一个常用来使用最新的JavaScript 语言特性的工具。——维基百科

前置知识

babel编译流程

babel其实就是将源码转换成目标源码的一个过程,大致分为三步

  • parse: 通过parser把源码转成抽象ast语法树
  • transform: 循环遍历ast,通过transform的能力对其进行语法转换
  • generate: 根据转换后的源码生产目标源码
主要依赖库介绍

@babel-core:babel核心编译库,它能够进行语法、语义、词法分析,生成抽象语法树**@babel-cli**:负责命令相关的功能,提供 bebel 命令**@babel/preset-env**:ES6稳定语法transform插件的集合**@babel/runtime**: 运行时,配合transform-runtime**@babel/plugin-transform-runtime**:polyfill垫片防止污染全局变量(第三方库必须得接入)@babel/polyfill:高级语法兼容解决方案依赖

学习babel,你主要掌握一下三个模块就差不多了:

  • 1、环境搭建,基本配置
  • 2、babel-polyfill
  • 3、babel-runtime

基本配置

搭建一个简单的项目
┌-- src
┆ └--index.js
├-- .babelrc
└-- package.json 

配置scripts命令

# package.json
{..."scripts": {"babel": "babel src/index.js --out-dir dist"},...
} 
安装

开发依赖

yarn add @babel/cli @babel/core @babel/plugin-transform-runtime @babel/preset-env -D 

生产依赖

yarn add @babel/polyfill @babel/runtime -S 
配置.babelrc
{"presets": [["@babel/preset-env"]],"plugins": []
} 

到这里一个最基础版本的babel就配置好了,运行看看src/index.js

const sum = (a, b) => a + b; 

输出dist/index.js

"use strict";

var sum = function sum(a, b) {return a + b;
}; 

证明babel已经可以将箭头函数转换为 function 函数了,大功告成!先别高兴太早,插播一段解释。。。。。。。

1、解释一下@babel/preset-env> 这个是ES6稳定语法编译插件的集合,什么意思?就是除掉一小部分高级语法(无法用js完整表示)以外的ES6语法转换成低版本js的插件的集合。> 举例:如果不用预设,上面src/inex.js中的箭头函数得单独安装@babel/plugin-transform-arrow-functions插件来完成转译

{
"presets": [], 
"plugins": ["@babel/plugin-transform-arrow-functions"],
//"targets": "last 2 Chrome versions"
} 

也是可以正常转译箭头函数,也就是说在babel中一种语法就得需要对应一个插件来转译,这里所说的@babel/preset-env预设就是很多稳定语法转译成低版本js插件的集合,目的是方便使用,减少配置成本。> 2、这里再补充一下几个官方的预设> @babel/preset-react:用来编译jsx语法> @babel/preset-typescript:用来将ts文件转成js文件> @babel/preset-flow:用来将使用flow类型约束的文件转成js文件> 3、既然babel是将高级语法转成低版本语法来做兼容处理,那到底要转到多低的版本呢???> @babel/preset-env会根据配置文件中的targets属性来生成插件列表后编译,在浏览器或electron中,官方还是推荐用.browserslistrc来配置目标环境。如果babel配置文件没有设置targetsignoreBrowserslistConfig,@babel/preset-env会使用默认的browserslist配置源(**> 0.5%, last 2 versions, Firefox ESR, not dead**

好了,来继续,来试试promise高级语法转译情况src/index.js

const sum = (a, b) => a + b;
// 新的 API
Promise.resolve(100).then((data) => data); 

编译后输出

"use strict";
var sum = function sum(a, b) {return a + b;
}; // 新的 API
Promise.resolve(100).then(function (data) {return data;
}); 

发现Promsie根本就没有转译,也就是说@babel/preset-env预设没法转译promsie,怎么解决???引入下一个知识点,@babel/polyfill,简称 “垫片”,说白了就是用这个来抹平部分高级语法的兼容问题

@babel/polyfill 垫片

@babel/polyfill其实是一个空壳,他当中包含 core-jsregenerate,真正起作用的是这两个依赖包

使用

在入口文件的顶部引入

import "@babel/polyfill"; 

执行编译,输出,都正常了

但是@babel/polyfill89.4kb完全引入了,而这里只需要promsie对应的垫片就OK了,造成编译出来的文件内存很大,又是一个头疼的问题来了!!!

官方出了解决方案,Babel@7.4.0版本之前,还是得用上面这种全量引入的方式,之后,可以分开引入

import "core-js/stable"; 
import "regenerator-runtime/runtime"; 

这也差不多,没多大效果,那有没有一种自动按需引入的解决方案呢?要说还得看官方,这不方案就来了吗

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

配置完后,编译,输出

"use strict";

require("core-js/modules/es.object.to-string.js");
require("core-js/modules/es.promise.js");
var sum = function sum(a, b) {return a + b;
}; // 新的 API
Promise.resolve(100).then(function (data) {return data;
}); 

完美解决!!!

到这里,如果自己的业务项目配置到此就结束了如果是开发第三方依赖包,还得继续往下看

@babel/plugin-transform-runtime

咱们不解释为啥,先看使用了@babel/plugin-transform-runtime插件和没使用输出的代码。src/index.js

class Test {} 

未使用的输出情况

"use strict";

require("core-js/modules/es.object.define-property.js");

function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }

function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

var Test = /*#__PURE__*/_createClass(function Test() {_classCallCheck(this, Test);
}); 

使用后的输出情况

"use strict";

var _interopRequireDefault = require("@babel/runtime-corejs3/helpers/interopRequireDefault");

var _createClass2 = _interopRequireDefault(require("@babel/runtime-corejs3/helpers/createClass"));

var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime-corejs3/helpers/classCallCheck"));

var Test = /*#__PURE__*/(0, _createClass2["default"])(function Test() {(0, _classCallCheck2["default"])(this, Test);
}); 

从两段输出代码可以看出,后一种是用变量来储存插件的方法,而且是采用抽离公共代码的helper文件导出方法的形式,而前一种则是把方法直接编译到了文件内,试想一下会出什么问题?

如果一个项目有多个地方用到了class类,转译时每个文件都要多出这段代码,造成严重的代码冗余,还有一点,直接将方法编译到文件会污染文件的全局环境,尤其是作为第三方类库提供给别人使用时,很可能被覆盖掉,应该避免不必要的冲突

@babel/runtime 和 @babel/plugin-transform-runtime这两个插件要配合使用,得同时安装

{"presets": [["@babel/preset-env",{"useBuiltIns": "usage","corejs": 3}]],"plugins": [["@babel/plugin-transform-runtime",{"absoluteRuntime": false,"corejs": 3,"helpers": true,"regenerator": true,"useESModules": false}]]
} 

结论:开发类库用polyfill + runtime,公司业务项目用polyfill就行了

最后

整理了一套《前端大厂面试宝典》,包含了HTML、CSS、JavaScript、HTTP、TCP协议、浏览器、VUE、React、数据结构和算法,一共201道面试题,并对每个问题作出了回答和解析。

有需要的小伙伴,可以点击文末卡片领取这份文档,无偿分享

部分文档展示:



文章篇幅有限,后面的内容就不一一展示了

有需要的小伙伴,可以点下方卡片免费领取

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值