Preface
Bronze Age
The most headache-inducing problem with front-end is browser compatibility, no matterjs
,stillcss
All need to consider browser compatibility issues,webpack
Before 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
webpack
After 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-runtime
The difference and how to configure the optimal solution
Add babel-loader to webpack
Install first@babel/core
,@babel/cli
,babel-loader
Bag
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-env
Yesgrammar
Convert it into code that the current browser can understand, pay attention to it only at the syntax level
Install@babel/preset-env
Need 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/polyfill
Yesapi
Convert 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/polyfill
All 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 solvepolyfill
On-demand loading issue,@babel/preset-env
Integratedpolyfill
, and can be configureduseBuildIns
Implement 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
usage
It 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 introduced,
good
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 useuseBuiltIns
The 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-env
The relevant parameters ofplugin-transform-runtime
Addedcorejs
Parameters, the polyfill requires method will no longer appear in the converted file. But it was introduced fromcore-js-stable
This 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!