iis服务器助手广告广告
返回顶部
首页 > 资讯 > 精选 >用了babel还需不需要polyfill
  • 684
分享到

用了babel还需不需要polyfill

2023-07-05 02:07:45 684人浏览 薄情痞子
摘要

本篇内容介绍了“用了babel还需不需要polyfill”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!啥是Babel甩出中文官方文档的定义B

本篇内容介绍了“用了babel还需不需要polyfill”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

    啥是Babel

    甩出中文官方文档的定义

    Babel 是一个工具链,主要用于将 ECMAScript 2015+ 版本的代码转换为向后兼容的 javascript 语法,以便能够运行在当前和旧版本的浏览器或其他环境中。 下面列出的是 Babel 能为你做的事情:

    • 语法转换

    • 通过 Polyfill 方式在目标环境中添加缺失的特性 (通过 @babel/polyfill 模块)

    • 源码转换 (codemods)

    • 更多! (查看这些 视频 获得启发)

    看完官方定义之后大家是不是觉得babel一个人就能把向后兼容的事情都做完了(不得不说确实有点误导),其实根本不是这样的。

    真实的情况是babel只是提供了一个“平台”,让更多有能力的plugins入驻我的平台,是这些plugins提供了将 ECMAScript 2015+ 版本的代码转换为向后兼容的 JavaScript 语法的能力。

    那么他是咋做到的呢?这就不得不提大名鼎鼎的AST了。

    Babel 工作原理

    babel的工作过程分为三个阶段:parsing(解析)、transfORMing(转化)、printing(生成)

    • parsing阶段babel内部的 babylon 负责将es6代码进行语法分析和词法分析后转换成抽象语法树

    • transforming阶段内部的 babel-traverse 负责对抽象语法树进行变换操作

    • printing阶段内部的 babel-generator 负责生成对应的代码

    其中第二步的转化是重中之重,babel的插件机制也是在这一步发挥作用的,plugins在这里进行操作,转化成新的AST,再交给第三步的babel-generator。 所以像我们上面说的如果没有这些plugins进驻平台,那么babel这个“平台”是不具备任何能力的。就好像这样:

    const babel = code => code;

    因此我们可以有信心的说出那个答案“需要”。不仅需要polyfill,还需要大量的plugins。

    下面我们通过例子来说明,以及还需要哪些plugins才能将 ECMAScript 2015+ 版本的代码完美的转换为向后兼容的 JavaScript 语法。

    preset-env, polyfill, plugin-transform-runtime 区别

    现在我们通过 npm init -y 来创建一个例子,然后安装 @babel/cli 和 @babel/core。 通过命令 babel index.js --out-file compiled.js 把 index 文件用 babel 编译成compiled.js

    // index.jsconst fn = () => {  console.log("wens");};const p = new Promise((resolve, reject) => {  resolve("wens");});const list = [1, 2, 3, 4].map(item => item * 2);

    不加任何plugins

    为了印证上面的说法,我们首先测试不加任何plugins的情况,结果如下

    //compiled.jsconst fn = () => {  console.log("wens");};const p = new Promise((resolve, reject) => {  resolve("wens");});const list = [1, 2, 3, 4].map(item => item * 2);

    编译好的文件没有任何变化,印证了我们上面的说法。接下来我们加入 plugins。

    在加入plugins测试之前我们需要知道一些前置知识,babel将ECMAScript 2015+ 版本的代码分为了两种情况处理:

    • 语法层: let、const、class、箭头函数等,这些需要在构建时进行转译,是指在语法层面上的转译

    • api方法层:Promise、includes、map等,这些是在全局或者Object、Array等的原型上新增的方法,它们可以由相应es5的方式重新定义

    babel对这两种情况的转译是不一样的,我们需要给出相应的配置。

    加入preset-env

    上面的例子种const,箭头函数属于语法层面的,而promise和map属于api方法层面的,现在我们加入 preset-env 看看效果

    // babel.config.jsmodule.exports = {  presets: ["@babel/env"],  plugins: []};

    babel 官方定义的 presets 配置项表示的是一堆plugins的集合,省的我们一个个的写plugins,他直接定义好了类似处理Reacttypescript等的preset

    //compiled.js"use strict";var fn = function fn() {  console.log("wens");};var p = new Promise(function (resolve, reject) {  resolve("wens");});var list = [1, 2, 3, 4].map(function (item) {  return item * 2;});

    果然从语法层面都降级了。那么api层面要如何处理呢? 下面我们加入 @bable/polyfill

    加入polyfill

    对于 polyfill 的定义,相信经常逛 mdn 的同学一定不会陌生, 他就是把当前浏览器不支持的方法通过用支持的方法重写来获得支持。

    项目中安装 @bable/polyfill ,然后 index.js 文件中引入

    // index.jsimport "@bable/polyfill";const fn = () => {  console.log("wens");};const p = new Promise((resolve, reject) => {  resolve("wens");});const list = [1, 2, 3, 4].map(item => item * 2);

    再次编译我们看看结果

    // compiled.js"use strict";require("@bable/polyfill");var fn = function fn() {  console.log("wens");};var p = new Promise(function (resolve, reject) {  resolve("wens");});var list = [1, 2, 3, 4].map(function (item) {  return item * 2;});

    没有别的变化,就多了一行require("@bable/polyfill"),其实这里就把这个库中的所有的polyfill都引入进来了,就好比我们项目中一股脑引入了全部的lodash方法。这样就支持了Promise和map方法。

    细心的同学一定会发现这样有点“蠢”啊,lodash都提供了按需加载,你这个一下都引入进来了,可我只需要Promise和map啊。别慌,我们接着往下看。

    配置 useBuiltIns

    上面我们通过 import "@bable/polyfill" 的方式来实现针对api层面的“抹平”。然而从 babel v7.4.0开始官方就不建议采取这样的方式了。 因为引入 @bable/polyfill 就相当于在代码中引入下面两个库

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

    这意味着不仅不能按需加载还有全局空间被污染的问题。因为他是通过向全局对象和内置对象的prototype上添加方法来实现的。

    因此 babel 决定把这两个人的工作一并交给上面我们提到的@babel/env,不仅不会全局污染还支持按需加载,岂不是妙哉。现在我们再来看看改造后的配置

    // index.js// 去掉了polyfillconst fn = () => {  console.log("wens");};const p = new Promise((resolve, reject) => {  resolve("wens");});const list = [1, 2, 3, 4].map(item => item * 2);
    // webpack.config.jsmodule.exports = {  presets: [    [      "@babel/env",      {        useBuiltIns: "usage", // 实现按需加载        corejs: {           version: 3,           proposals: true         }      }    ]  ],  plugins: []};

    通过给 @babel/env 配置 useBuiltIns 和 corejs 属性,我们实现了polyfill方法的按需加载。关于全部配置项,参加官方文档

    // compiled.js"use strict";require("core-js/modules/es.array.map");require("core-js/modules/es.object.to-string");require("core-js/modules/es.promise");var fn = function fn() {  console.log("wens");};var p = new Promise(function (resolve, reject) {  resolve("wens");});var list = [1, 2, 3, 4].map(function (item) {  return item * 2;});

    编译后的js文件只require了需要的方法,完美。那么我们还有可以优化的空间吗?有的有的,我们接着往下看。

    加入 @babel/plugin-transform-runtime

    改造上面的例子

    // index.jsclass Person {  constructor(name) {    this.name = name;  }  say() {    console.log(this.name);  }}

    只转换一个 Person 类,我们看看转换后的文件长啥样

    // compiled.js "use strict";require("core-js/modules/es.function.name");require("core-js/modules/es.object.define-property");function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }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); return Constructor; }var Person = function () {  function Person(name) {    _classCallCheck(this, Person);    this.name = name;  }  _createClass(Person, [{    key: "say",    value: function say() {      console.log(this.name);    }  }]);  return Person;}();

    除了require的部分,还多了好多自定义的函数。同学们想一想,现在只有一个index文件需要转换,然而实际项目开发中会有大量的需要转换的文件,如果每一个转换后的文件中都存在相同的函数,那岂不是浪费了,怎么才能把重复的函数去掉呢?

    plugin-transform-runtime 闪亮登场。

    上面出现的_classCallCheck,_defineProperties,_createClass三个函数叫做辅助函数,是在编译阶段辅助 Babel 的函数。

    当使用了plugin-transform-runtime插件后,就可以将babel转译时添加到文件中的内联辅助函数统一隔离到babel-runtime提供的helper模块中,编译时,直接从helper模块加载,不在每个文件中重复的定义辅助函数,从而减少包的尺寸,下面我们看下效果:

    // WEBpack.config.jsmodule.exports = {  presets: [    [      "@babel/env",      {        useBuiltIns: "usage",        corejs: { version: 3, proposals: true }      }    ]  ],  plugins: ["@babel/plugin-transform-runtime"]};
    // compiled.js"use strict";var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");require("core-js/modules/es.function.name");var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));var Person = function () {  function Person(name) {    (0, _classCallCheck2["default"])(this, Person);    this.name = name;  }  (0, _createClass2["default"])(Person, [{    key: "say",    value: function say() {      console.log(this.name);    }  }]);  return Person;}();

    完美的解决了代码冗余的问题。 你们以为这就结束了吗,还没有。仔细看到这里的同学应该注意到了虽然上面使用 useBuiltIns 配置项实现了poilyfill的按需引用,可是他还存在全局变量污染的情况,就好比这句代码,重写了array的prototype方法,造成了全局污染。

    require("core-js/modules/es.array.map");

    最后再改造一次babel的配置文件

    // webpack.config.jsmodule.exports = {  presets: ["@babel/env"],  plugins: [    [      "@babel/plugin-transform-runtime",      {        corejs: { version: 3 }      }    ]  ]};

    我们看到去掉了 @babel/env 的相关参数,而给 plugin-transform-runtime 添加了corejs参数,最终转换后的文件不会再出现polyfill的require的方法了。

    // compiled.js"use strict";var _interopRequireDefault = require("@babel/runtime-corejs3/helpers/interopRequireDefault");var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime-corejs3/helpers/classCallCheck"));var _createClass2 = _interopRequireDefault(require("@babel/runtime-corejs3/helpers/createClass"));var Person = function () {  function Person(name) {    (0, _classCallCheck2["default"])(this, Person);    this.name = name;  }  (0, _createClass2["default"])(Person, [{    key: "say",    value: function say() {      console.log(this.name);    }  }]);  return Person;}();

    综上所述,plugin-transform-runtime 插件借助babel-runtime实现了下面两个重要的功能

    • 对辅助函数的复用,解决转译语法层时出现的代码冗余

    • 解决转译api层出现的全局变量污染

    “用了babel还需不需要polyfill”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注编程网网站,小编将为大家输出更多高质量的实用文章!

    --结束END--

    本文标题: 用了babel还需不需要polyfill

    本文链接: https://www.lsjlt.com/news/349081.html(转载时请注明来源链接)

    有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

    本篇文章演示代码以及资料文档资料下载

    下载Word文档到电脑,方便收藏和打印~

    下载Word文档
    猜你喜欢
    • 用了babel还需不需要polyfill
      本篇内容介绍了“用了babel还需不需要polyfill”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!啥是Babel甩出中文官方文档的定义B...
      99+
      2023-07-05
    • 用了babel还需要polyfill吗原理解析
      目录引言啥是BabelBabel 工作原理preset-env, polyfill, plugin-transform-runtime 区别不加任何plugins加入preset-e...
      99+
      2023-02-05
      babel polyfill原理 babel polyfill
    • Win7中如何删除还原点不需要它了
        微软的系统很早就带有系统还原功能,但在我们熟知的XP时代,在电脑中使用还原功能还是很麻烦的,并不好用。现在在Win7系统中,系统还原功能得到了很好的改进,使用起来已经非常方便。   在Win7系统中,右击&ldquo...
      99+
      2023-06-03
      win7 删除还原点 还原点 Win7
    • 安装了mysql还需要安装phpMyAdmin吗
      这篇文章主要介绍安装了mysql还需要安装phpMyAdmin吗,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!安装了mysql是否需要安装phpMyAdmin如果是对mysql命令行...
      99+
      2024-04-02
    • mysql需不需要commit
      这篇文章主要介绍了mysql需不需要commit的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇mysql需不需要commit文章都会有所收获,下面我们一起来看看吧。 ...
      99+
      2024-04-02
    • 有了Spring为什么还需要SpringBoot呢
      目录 一、Spring缺点分析 二、什么是Spring Boot 三、Spring Boot的核心功能 3.1 起步依赖 3.2 自动装配 一、Spring缺点分析 1. 配置文件和依赖太多了!!! spring是一个非常优秀的轻...
      99+
      2023-09-23
      spring spring boot java maven 原力计划
    • 安装了gitlab还需要安装git吗
      在进行代码管理时,Git是一款极为常用的版本控制工具,而GitLab则是一种基于Git的Web界面式的代码仓库管理系统,它提供了用户管理、代码仓库管理、代码审核等一系列功能。GitLab中已经使用了Git,那么安装了GitLab还需要再安装...
      99+
      2023-10-22
    • 网站上线除了备案还需要什么
      网站上线除了备案还需要具备以下条件购买网站域名域名就是用户通过互联网访问网站的地址。可以选择一家提供域名注册服务的平台,查询想要注册的域名是否被注册,如果没有被注册,进行注册购买即可。选择网站空间网站空间就是用于存放网站数据的地方。空间产品...
      99+
      2024-04-02
    • JavaScript 中有了Object 为什么还需要 Map 呢
      目录一、别把对象当 Map1、可能通过原型链访问到未定义的属性2、对象的 Key 只能是字符串二、使用 Map1、Map 常用操作2、遍历 Map3、Map 中判断 key 相等4、...
      99+
      2024-04-02
    • laravel定时任务需不需要用cron
      这篇文章主要介绍“laravel定时任务需不需要用cron”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“laravel定时任务需不需要用cron”文章能帮助大家解决问题。laravel定时任务需要用...
      99+
      2023-06-30
    • 使用javascript需不需要安装什么
      这篇文章主要介绍“使用javascript需不需要安装什么”,在日常操作中,相信很多人在使用javascript需不需要安装什么问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”...
      99+
      2024-04-02
    • 云主机需不需要备案
      本篇内容介绍了“云主机需不需要备案”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!首先,云主机就是一种虚拟化的技术,它是一个集群上虚拟分来多个...
      99+
      2023-06-07
    • 计算机中装了navicat还需要装mysql吗
      小编给大家分享一下计算机中装了navicat还需要装mysql吗,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!  很多小伙伴还不...
      99+
      2024-04-02
    • 修改php.ini需不需要重启
      这篇“修改php.ini需不需要重启”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“修改php.ini需不需要重启”文章吧。修...
      99+
      2023-07-05
    • go语言需不需要分号
      这篇文章主要介绍了go语言需不需要分号的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇go语言需不需要分号文章都会有所收获,下面我们一起来看看吧。Go语言不需要在语句或者声明的末尾添加分号,除非一行上有多条语句。...
      99+
      2023-07-04
    • 有了ChatGPT编程是否还需要那么多库
      这篇文章主要介绍了有了ChatGPT编程是否还需要那么多库的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇有了ChatGPT编程是否还需要那么多库文章都会有所收获,下面我们一起来看看吧。瀑布流展示图片的新需求我已...
      99+
      2023-07-05
    • 买了云服务器还需要买数据库吗
      如果您是购买云服务器后直接添加或更新数据库,则不需要再购买数据库。但是,如果您将数据库用于其他目的(例如备份和还原数据或分发用户数据),则可能需要购买数据库,以便可以进行数据库管理和操作。 在大多数云计算提供商中,您可以使用他们的云存储服...
      99+
      2023-10-26
      买了 要买 还需
    • c++中abs需不需要头文件
      是的,在 c++ 中使用 abs() 函数需要包含 头文件,具体步骤如下:使用 #include 包含头文件。使用 abs() 函数计算绝对值。 C++ 中使用 abs() 函数是...
      99+
      2024-05-07
      c++ 标准库
    • javascript的变量需不需要声明
      这篇文章主要介绍“javascript的变量需不需要声明”,在日常操作中,相信很多人在javascript的变量需不需要声明问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”ja...
      99+
      2024-04-02
    • 用阿里云还需要服务器吗
      简介 在互联网时代,服务器成为了企业和个人的重要基础设施之一。而阿里云作为国内领先的云计算服务提供商,提供了丰富多样的云服务器产品。然而,很多人会疑惑:使用阿里云还需要自己购买服务器吗?本文将对这个问题进行探讨,并给出一些实际案例来说明。阿...
      99+
      2023-12-31
      阿里 还需要 服务器
    软考高级职称资格查询
    编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
    • 官方手机版

    • 微信公众号

    • 商务合作