我的编程空间,编程开发者的网络收藏夹
学习永远不晚

用了babel还需不需要polyfill

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

用了babel还需不需要polyfill

本篇内容介绍了“用了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,他直接定义好了类似处理react,typescript等的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”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注编程网网站,小编将为大家输出更多高质量的实用文章!

    免责声明:

    ① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

    ② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

    用了babel还需不需要polyfill

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

    下载Word文档

    猜你喜欢

    用了babel还需不需要polyfill

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

    用了babel还需要polyfill吗原理解析

    这篇文章主要为大家介绍了用了babel是否还需要polyfill的原理解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-02-05

    Win7中如何删除还原点不需要它了

    微软的系统很早就带有系统还原功能,但在我们熟知的XP时代,在电脑中使用还原功能还是很麻烦的,并不好用。现在在Win7系统中,系统还原功能得到了很好的改进,使用起来已经非python常方便。在Win7系统中,右击“计算机&编程rd
    2023-06-03

    安装了gitlab还需要安装git吗

    在进行代码管理时,Git是一款极为常用的版本控制工具,而GitLab则是一种基于Git的Web界面式的代码仓库管理系统,它提供了用户管理、代码仓库管理、代码审核等一系列功能。GitLab中已经使用了Git,那么安装了GitLab还需要再安装
    2023-10-22

    软考中级需要一次过吗?过了一门还需要再考吗

    软考中级考试需要一次性通过所有科目,若其中有一科没有达到及格分数线,那么考试将不予通过,且成绩也不能保留。这意味着,如果考生在某次考试中只通过了一门科目,那么在下一次考试时,需要重新参加所有科目的考试。
    软考中级需要一次过吗?过了一门还需要再考吗
    2024-10-03

    laravel定时任务需不需要用cron

    这篇文章主要介绍“laravel定时任务需不需要用cron”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“laravel定时任务需不需要用cron”文章能帮助大家解决问题。laravel定时任务需要用
    2023-06-30

    买了云服务器还需要买数据库吗

    如果您是购买云服务器后直接添加或更新数据库,则不需要再购买数据库。但是,如果您将数据库用于其他目的(例如备份和还原数据或分发用户数据),则可能需要购买数据库,以便可以进行数据库管理和操作。在大多数云计算提供商中,您可以使用他们的云存储服务或者自定义数据库来存储数据。这些数据库通常可以从多个来源(例如本地文件系统或云存储)中进行访问,并且可以进行数据备份,以确保数据的可用性和可追溯性。如果您将
    2023-10-26

    有了ChatGPT编程是否还需要那么多库

    这篇文章主要介绍了有了ChatGPT编程是否还需要那么多库的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇有了ChatGPT编程是否还需要那么多库文章都会有所收获,下面我们一起来看看吧。瀑布流展示图片的新需求我已
    2023-07-05

    用阿里云还需要服务器吗

    简介在互联网时代,服务器成为了企业和个人的重要基础设施之一。而阿里云作为国内领先的云计算服务提供商,提供了丰富多样的云服务器产品。然而,很多人会疑惑:使用阿里云还需要自己购买服务器吗?本文将对这个问题进行探讨,并给出一些实际案例来说明。阿里云服务器的优势阿里云提供了多种类型的云服务器产品,包括弹性计算、容器服务、裸金属
    用阿里云还需要服务器吗
    2023-12-31

    买了阿里云是否还需要购买数据库?

    随着云计算技术的不断发展,越来越多的企业开始转向阿里云等云服务提供商。然而,购买阿里云是否还需要购买数据库呢?本文将对此进行详细说明。随着互联网技术的飞速发展,云计算已经成为企业进行信息化建设的重要手段之一。阿里云作为国内最大的云计算服务提供商,其产品和服务深受广大用户的喜爱。然而,购买阿里云是否还需要购买数据库
    买了阿里云是否还需要购买数据库?
    2023-12-15

    工具对比:安装了git还需要安装gitlab吗

    随着软件开发工具的不断更新,Git已经成为许多开发人员的首选版本控制系统。但是,Git是一个分散的版本控制系统,它缺乏一些Web界面以方便代码管理和协作。因此,一些开发人员选择安装GitLab,这是一种开源的代码协作平台。但是,安装了Git
    2023-10-22

    买了阿里云服务器还需要买数据库吗

    在阿里云服务器上,您可以选择使用云数据库RDS来存储您的数据,也可以选择在服务器上自行安装数据库软件,如MySQL、MongoDB等。如果您选择使用云数据库RDS,您需要购买相应的RDS实例,而如果您选择在服务器上自行安装数据库软件,则不需要再购买数据库服务。需要注意的是,如果您选择在服务器上自行安装数据库软件,您需要自行负责数据库的安全、备份、维护等工作,而使用云数据库RDS则可以享受阿里云
    2023-10-26

    编程热搜

    • Python 学习之路 - Python
      一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
      Python 学习之路 - Python
    • chatgpt的中文全称是什么
      chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
      chatgpt的中文全称是什么
    • C/C++中extern函数使用详解
    • C/C++可变参数的使用
      可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
      C/C++可变参数的使用
    • css样式文件该放在哪里
    • php中数组下标必须是连续的吗
    • Python 3 教程
      Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
      Python 3 教程
    • Python pip包管理
      一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
      Python pip包管理
    • ubuntu如何重新编译内核
    • 改善Java代码之慎用java动态编译

    目录