SoFunction
Updated on 2025-04-06

Detailed explanation of how polyfills loads on demand and detailed explanation of scenario examples

Preface

Bronze Age

The most headache-inducing problem with front-end is browser compatibility, no matterjs,stillcssAll need to consider browser compatibility issues,webpackBefore coming out, this was nothing more than a very headache. It took a long time to find a compatibility issue, find a lot of information, solve it, and then another problem came out. It would undoubtedly take a long time to solve it, which undoubtedly wastes valuable time to fish.

The Age of Muskets

webpackAfter coming out, the efficiency has increased several times, but one problem is that the configuration is complicated. Some friends, including me, may not understand it yet.@babel/preset-env,@babel/polyfills, @babel/plugin-transform-runtimeThe difference and how to configure the optimal solution

Add babel-loader to webpack

Install first@babel/core,@babel/cli,babel-loaderBag

content

const fn = () => {
  ('ws');
}
const array = [1, 2, 3, 4];
(1);

Compile ·

  "scripts": {
    "build": "babel src --out-dir build"
  },

Then compile

const fn = () => {
  ('ws');
};
const array = [1, 2, 3, 4];
(1);

I found that the code is almost the same as my one, no change

Before adding plugins tests, we need to know some pre-knowledge. Babel divides the code of ECMAScript 2015+ into two situations:

  • Syntax layer: let, const, class, arrow functions, etc. These need to be translated at the construction time, refer to translation at the grammatical level.
  • Api method layer: Promise, include, map, etc. These are new methods added to global or Object, Array, etc. They can be redefined by the corresponding ES5 method

Babel's translation of these two situations is different, and we need to give the corresponding configuration.

@babel/preset-env

@babel/preset-envYesgrammarConvert it into code that the current browser can understand, pay attention to it only at the syntax level

Install@babel/preset-envNeed to be inMake configuration

 = {
  presets: ["@babel/preset-env"]
}

Then let's look at the print results

"use strict";
var fn = function fn() {
  ('ws');
};
var array = [1, 2, 3, 4];
(1);

The arrow function has been transformed because the arrow function is syntactical.

@babel/polyfill

@babel/polyfillYesapiConvert into code that the current browser can understand, here is convertedapi

The use of the library needs to beIntroduced@babel/polyfill

import "@babel/polyfill";
const fn = () => {
  ('ws');
}
const array = [1, 2, 3, 4];
(1);

After compiling, we found that our code has not changed much, but it did@babel/polyfillAll of them are attracted by it. You should know that @babel/polyfill is very large, including all APIs, which will undoubtedly make the packaging volume much larger.

"use strict";
require("@babel/polyfill");
var fn = function fn() {
  ('ws');
};
var array = [1, 2, 3, 4];
(1);

This is not what we want, we just want methods, we need to load on demand, not load so much code

Don't panic, I'll talk about it next

Configure useBuiltIns

To solvepolyfillOn-demand loading issue,@babel/preset-envIntegratedpolyfill, and can be configureduseBuildInsImplement on-demand loading

corejsIt also needs to be configured at the same time. Version 2 can handle global objects, but the instance method does not handle it, so version 3 is used here.

npm install core-js@3

usageIt will be based on the configuration browser compatibility and the API used in your code.polyfill, realizes on-demand addition.

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

Check our packaging results now

"use strict";
require("core-js/modules/");
var fn = function fn() {
  ('ws');
};
var array = [1, 2, 3, 4];
(1);

Only introducedgood

Join @babel/plugin-transform-runtime

Renovate the above examples

......
class Person {
  constructor(name) {
     = name;
  }
  say() {
    ();
  }
}

Only convert one Person class, let's see what the converted file looks like

"use strict";
require("core-js/modules/");
require("core-js/modules/");
require("core-js/modules/");
require("core-js/modules/");
require("core-js/modules/");
require("core-js/modules/");
require("core-js/modules/");
require("core-js/modules/");
require("core-js/modules/");
require("core-js/modules/");
require("core-js/modules/");
function _typeof(obj) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof  ? function (obj) { return typeof obj; } : function (obj) { return obj && "function" == typeof Symbol &&  === Symbol && obj !==  ? "symbol" : typeof obj; }, _typeof(obj); }
require("core-js/modules/");
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 < ; i++) { var descriptor = props[i];  =  || false;  = true; if ("value" in descriptor)  = true; (target, _toPropertyKey(), descriptor); } }
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); (Constructor, "prototype", { writable: false }); return Constructor; }
function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return _typeof(key) === "symbol" ? key : String(key); }
function _toPrimitive(input, hint) { if (_typeof(input) !== "object" || input === null) return input; var prim = input[]; if (prim !== undefined) { var res = (input, hint || "default"); if (_typeof(res) !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
var fn = function fn() {
  ('ws');
};
var array = [1, 2, 3, 4];
(1);
var Person = /*#__PURE__*/function () {
  function Person(name) {
    _classCallCheck(this, Person);
     = name;
  }
  _createClass(Person, [{
    key: "say",
    value: function say() {
      ();
    }
  }]);
  return Person;
}();

In addition to the require part, there are also many custom functions. Students, think about it, now there is only one index file that needs to be converted, but there will be a large number of files that need to be converted in actual project development. If the same function exists in each converted file, wouldn’t it be a waste? How can we remove the duplicate functions?

plugin-transform-runtime made a brilliant debut.

The three functions _classCallCheck, _defineProperties, and _createClass appearing above are called helper functions, which are functions that assist Babel during the compilation stage.

After using the plugin-transform-runtime plug-in, the inline helper functions added to the file that are added to the babel translation time can be uniformly isolated into the helper module provided by babel-runtime. During compilation, it is directly loaded from the helper module and does not repeatedly define the helper function in each file, thereby reducing the size of the package. Let's take a look at the effect below:

// 
 = {
  presets: [
    [
      "@babel/env",
      {
        useBuiltIns: "usage",
        corejs: { version: 3, proposals: true }
      }
    ]
  ],
  plugins: ["@babel/plugin-transform-runtime"]
};
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
require("core-js/modules/");
var fn = function fn() {
  ('ws');
};
var array = [1, 2, 3, 4];
(1);
var Person = /*#__PURE__*/function () {
  function Person(name) {
    (0, _classCallCheck2.default)(this, Person);
     = name;
  }
  (0, _createClass2.default)(Person, [{
    key: "say",
    value: function say() {
      ();
    }
  }]);
  return Person;
}();

Perfectly solves the problem of code redundancy. Do you think this is over? Not yet. Students who see this carefully should notice that although the above useuseBuiltInsThe configuration item implements on-demand reference of poilyfill, but it still has global variable pollution. Just like this code, it rewrites the prototype method of array, causing global pollution.

require("core-js/modules/");

Finally, rebuild the configuration file of the babel

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

Removed@babel/preset-envThe relevant parameters ofplugin-transform-runtimeAddedcorejsParameters, the polyfill requires method will no longer appear in the converted file. But it was introduced fromcore-js-stableThis solves the global variable pollution caused by the translation API layer

"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 _includes = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/instance/includes"));
var fn = function fn() {
  ('ws');
};
var array = [1, 2, 3, 4];
(0, _includes.default)(array).call(array, 1);
var Person = /*#__PURE__*/function () {
  function Person(name) {
    (0, _classCallCheck2.default)(this, Person);
     = name;
  }
  (0, _createClass2.default)(Person, [{
    key: "say",
    value: function say() {
      ();
    }
  }]);
  return Person;
}();

To sum up, the plugin-transform-runtime plug-in realizes the following two important functions with the help of babel-runtime.

  • Multiplexing of helper functions to solve the code redundancy that occurs when translating the syntax layer
  • Solve global variable pollution in the translation API layer

refer to

  • Do you still need polyfill after using babel? ? ?
  • babel7 - Loading polyfill on demand - chenby
  • Webpack5 Series (IV): Babel Configuration

The above is a detailed explanation of how polyfills loads on demand and scenario examples. For more information about polyfills loading on demand, please pay attention to my other related articles!