Optimization of Babel – loader
Babel-loader is always the loader that handles the most tasks, especially during React development, there are a lot of JSX to parse and compile. Some optimizations can be made starting with the babel-Loader configuration items. The set of plug-ins used by babel-loader is mainly @babel/preset-env and @babel/preset- React.
@babel/preset-env
@babel/preset-env is a collection of plug-ins responsible for compiling JS code into more compatible lower versions of JS code.
Configuration items
Configuration items | type | The default value | meaning |
---|---|---|---|
targets |
String|Array|Object |
{} |
Configure the browser version or nodeJS version |
bugfixes |
Boolean |
false |
Depending on thetargets Set, according totargets To compile the latest version of the syntax supported by the target browser; This will be enabled automatically with Babel 8 |
spec |
Boolean |
false |
Enabling more specifications leads to slower compilations |
loose |
Boolean |
false |
Lax compilation rules. Normally, compilation follows ECMAScript 6 semantics as much as possible, but lax mode is lax and looks like handwritten code, see –Babel 6: loose mode |
modules |
"amd"|"umd"|"systemjs"|"commonjs"|"cjs"|"auto"|false |
"auto" |
Rules for converting ES Module syntax to other types of modules |
debug |
Boolean |
false |
Output plugin and Polyfill used to the console, this configuration is not subject to Webpackstats The influence of |
include |
Array |
[] |
Customize the name of the plug-in |
exclude |
Array |
[] |
Exclude plug-ins used |
useBuiltIns |
"usage"|"entry"|false |
false |
Define how to handle polyfill |
corejs |
2 .3 .{version: 2|3,proposals: boolean} |
2 |
Only in theuseBuiltIns: usage oruseBuiltIns: entry The definitioncore-js Version,version It has to be the number 2 or 3 |
forceAllTransforms |
Boolean |
false |
Disabling all compilations |
configPath |
String |
The current working directory of the Node.js process | The configuration specifiesbrowserslist The directory where the |
ignoreBrowserslistConfig |
Boolean |
false |
Whether to ignorebrowserslist configuration |
browserslistEnv |
Object |
undefined |
Configure for different development environmentsbrowserslist |
shippedProposals |
Boolean |
false |
Whether to enable a proposal already supported by the browser |
Configure modules
The modules configuration item by default determines whether the browser supports some features of ES Modules based on the caller inside Babel. For example, whether the browser supports static import or dynamic import() syntax. Choose to further convert ES Module to CommonJS require syntax.
Since the tree Shaking feature built into Webpack relies on static parsing of ES Modules, Modules are not supported at all in IE 11, so it is up to you to disable Modules.
Configure the targets
An earlier Version of Babel was preset, called babel-preset-latest, which is preset to automatically add a plugin according to the new features of the ES specification, saving the developer from having to preset separately. But just adding them would lead to more and more plug-ins, and as time goes on, most OF ES6 syntax is now supported by mainstream browsers, there is no need to use those plug-ins to compile, and the useless plug-ins left in preset will cause the compilation process of Babel to be slowed down. It is recommended to use @babel/preset-env instead of this preset.
@babel/preset-env helps developers transition from preset-latest, if targets are not configured in @babel/preset-env, it will compile all ES6+ JS code into ES5 by default. By enabling the @babel/preset-env debug option, you can clearly see how many plugins @babel/ Preset -env is used on the console. If targets are not set, the most preset plugin will be introduced as shown in the figure below.
In a development environment, these plugins are mostly unnecessary, and @babel/preset-env does not look up browserslist configuration. Even the default browserslist configuration must be configured in targets. This may be revisited in Babel 8.
{
"presets": [["@babel/preset-env", { "targets": "defaults"}}]]Copy the code
The Targets field also supports the browserslist configuration as described above. The development environment always uses the latest version of Chrome, thus reducing the amount of plugin introduced by the development environment.
{
targets: isDevelopment
? "last 1 chrome version"
: "> 1%, last 2 versions, Firefox ESR, ie >= 11, not dead",}Copy the code
Targets also supports the configuration of some special fields:
esmodules
Default is:false
, specify that the target browser supports ES Modules syntax if set totrue
, thenbrowserslist
The configuration of thenode
:"current" | true
, specifying that the current version of Node is compiledsafari
:"tp"
Specifies that the technical preview version of Safari is compiledbrowsers
: Specify abrowserslist
Rule array, not recommended, as it may be removed in a future release
Configuration bugfixes
By default, @babel/preset-env or other Babel plugin will group ES syntax features, such as function arguments including default parameters, preset parameters, etc. If bugfixes is enabled, The @babel/preset-env selects different groups to compile to the nearest latest modern syntax supported by the target browser based on the targets compatibility range, which results in a significant reduction in the size of the compiled application, optimizing not only the webpack build speed, but also the generated code.
Configuration polyfill
The core – js profile
core-js#babelpreset-env
@babel/ Polyfill has been deprecated since version 7.4. Core-js is currently the dominant polyfill scheme.
Core-js itself comes in three versions:
Yarn add [email protected]
: global injection version, which only needs to be imported globally at the code entry pointcore-js
Can beYarn add [email protected]
: Module import version, need to introduce the corresponding Polyfill module file separately when usingcore-js-bundle
: Uses the script injection version
In addition, each version also has modules containing different features:
core-js(-pure)/es
:es
Represents stable ES specification contentcore-js(-pure)/stable
:stable
Includes both stable WHATWG specification content and ES specification contentcore-js(-pure)/features
:features
Contains only the module-specific content of the individual syntax, for examplecore-js(-pure)/features/set
Contains onlySet
Data set related to polyfill
If you use the globally-injected version, you can import only globally in the project entry file. Global import automatically introduces polyfills based on the target environment, not on demand. You can also use Features to inject only as many polyfills as you need.
// Global injection
import 'core-js';
Array.from(new Set([1.2.3.2.1]));
[1[2.3], [4[5]]].flat(2);
Promise.resolve(32).then(x= > console.log(x));
// Introduce the required module through feature
import 'core-js/features/array/from';
import 'core-js/features/array/flat';
import 'core-js/features/set';
import 'core-js/features/promise';
Array.from(new Set([1.2.3.2.1]));
[1[2.3], [4[5]]].flat(2);
Promise.resolve(32).then(x= > console.log(x));
Copy the code
Import ‘core-js-pure’ cannot be used if using the pure version; In this global injection approach, specific modules need to be imported as needed; Pure version can be introduced on demand, but it is very troublesome to use, for example, two features, Set and array. from, need to find out how to introduce these two features.
import from from 'core-js-pure/features/array/from';
import flat from 'core-js-pure/features/array/flat';
import Set from 'core-js-pure/features/set';
import Promise from 'core-js-pure/features/promise';
from(new Set([1.2.3.2.1])); // => [1, 2, 3]
flat([1[2.3], [4[5]]].2); // => [1, 2, 3, 4, 5]
Promise.resolve(32).then(x= > console.log(x));
Copy the code
UseBuiltIns and corejs
Note: The useBuiltIns and Corejs properties of @babel/preset-env are not required if core-js-pure is used. The @babel/ plugin-transform-Runtime can be used to simplify the coding.
For globally injected versions, such as core-js@3 after installation, the @babel/preset-env corejs configuration item needs to be set first, and it is recommended to specify a smaller core-js version number, such as 3.6 instead of 3, because for corejs: 3. Modules added in smaller core-JS versions will not be added. By default, only the stable ES feature will be adopted. Polyfill will not be introduced for the specification content that is still in the state of the proposal, but corejs.proposals can enable support for the proposal content.
You must then specify useBuiltIns, otherwise no polyfills will be added.
For the global injection version of core-JS, specify corejs: “3.6” and useBuiltIns: “Entry”.
module: {
rules: [{test: /\.m? js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader'.options: {
presets: [
'@babel/preset-env',
{
debug: true.// Enable the debug mode
targets: 'ie >= 8'.bugfixes: true.modules: false.corejs: {
version: 3.proposals: true,},useBuiltIns: 'entry',},],},},},]; }Copy the code
When useBuiltIns:”entry” is specified, all core-JS polyfills for targets are packed in. This is a nightmare! When I only used the two features Set and Array.from in the entrance, I packed them for 1 minute and generated a 150KB Polyfill chunk
import 'core-js';
console.log(Array.from(new Set([1.2.3.2.1)));Copy the code
When useBuiltIns:”usage” is specified, only the required polyfills are introduced according to the code, and the corresponding packaging time and chunk size are reduced considerably, to about 20KB.
UseBuiltIns: Usage is not stable until Babel 7.3, and sometimes required polyfills are not automatically added, so there may be some problems with older projects. As a better option for compatibility and on-demand introduction, the following combination of core-js-pure and @babel/ plugin-transform-Runtime can be used.
@babel/preset-react
@babel/preset- React preset is responsible for switching JSX and other grammars.
Configuration items
Configuration items | type | The default value | meaning |
---|---|---|---|
runtime |
"Classic" or "automatic" |
"classic" |
Whether to automatically import JSX converted functions. Default: No |
development |
Boolean |
false |
Whether to enable the development environment. Plug-ins for development assistance will be enabled for the development environment, for example:@babel/plugin-transform-react-jsx-self 和 @babel/plugin-transform-react-jsx-source |
throwIfNamespace |
Boolean |
false |
Whether using tag names in XML namespaces is a throw error; For example,<f:image /> Form, although permitted by the JSX specification, is prohibited by default because the React JSX does not currently support it |
importSource |
String |
react |
Sets the name of the function import source |
pragma |
String |
React.createElement |
Replace the functions used when compiling JSX expressions |
pragmaFrag |
String |
React.Fragment |
Set JSX Fragments syntactically converted functions |
useBuiltIns |
Boolean |
false |
Whether to use the native built-in Polyfill instead of polyfill through another plug-in |
useSpread |
Boolean |
false |
When aprops Use inline object instead of using Babel extension orObject.assign Copy the object |
Inline object:
{
(firstName = 'john'), (lastName = 'walter');
}
Copy the code
Configure @babel/preset- React for different environments to use development-assisted plug-ins in the development environment
module: {
rules: [{test: /\.m? js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader'.options: {
presets: [
'@babel/preset-env'['@babel/preset-react',
{
development: isDevelopment, // Development environment
useBuiltIns: true,},],],},},},]; }Copy the code
@babel/plugin-transform-runtime
Babel inserts very small auxiliary code into the source code that needs to be compiled, and sometimes this code is duplicated, increasing the size of the code. This plugin can disable Babel’s automatic runtime injection for each file with @babel/plugin-transform-runtime. Then install @babel/ Runtime to introduce Babel’s auxiliary code as a separate dependency module, so that the compiled code can avoid repeated auxiliary code and reduce the size of the code.
yarn add @babel/plugin-transform-runtime @babel/runtime -D
Copy the code
module.exports = {
module: {
rules: [{test: /\.m? js$/,
exclude: /(node_modules)/,
loader: 'babel-loader'.options: {
presets: ['@babel/preset-env'].plugins: ['@babel/plugin-transform-runtime'],},},],},};Copy the code
@babel/ plugin-transform-Runtime performs three tasks:
- When using generators or asynchrony in a project
async
Function is automatically introduced@babel/plugin-transform-runtime
- use
core-js
Polyfill can be passedcorejs
configuration - By default, the helper code for Babel is removed
@babel/runtime/helpers
Instead, the optimization to reduce the size of the code mentioned above, can be passedhelpers
Select Enable or not
Configuration items
Configuration items | type | The default value | meaning |
---|---|---|---|
corejs |
false 2, 3 {version: 2 or 3, proposals: Boolean} |
false |
The specifiedcore-js The version of the library |
helpers |
Boolean |
true |
Whether to switch the auxiliary code inserted by Babel to a module call |
regenerator |
Boolean |
true |
Whether to convert generator functions to run-time generators that do not pollute the global scope |
useESModules |
Boolean |
false |
Whether to use auxiliary code conversion does not pass@babel/plugin-transform-modules-commonjs The code of |
absoluteRuntime |
Boolean orString |
false |
|
version |
String |
false |
The specified@babel/runtime-corejs The version of the |
polyfill
Another use of this plugin is to polyfill with the Pure version of the core-js-Pure library to simplify the import syntax of core-js-Pure. For example, the syntax of importing modules is automatically converted.
// The original core-js-pure usage
import from from 'core-js-pure/stable/array/from';
import flat from 'core-js-pure/stable/array/flat';
import Set from 'core-js-pure/stable/set';
import Promise from 'core-js-pure/stable/promise';
from(new Set([1.2.3.2.1]));
flat([1[2.3], [4[5]]].2);
Promise.resolve(32).then(x= > console.log(x));
// introduce a simplified version of @babel/plugin-transform-runtime
Array.from(new Set([1.2.3.2.1]));
[1[2.3], [4[5]]].flat(2);
Promise.resolve(32).then(x= > console.log(x));
Copy the code
Using @babel/ plugin-transform-Runtime in conjunction with core-js-pure requires the installation of the corresponding @babel/ Runtime library
corejs |
Corresponding installed library |
---|---|
false |
yarn add @babel/runtime |
2 |
yarn add @babel/runtime-corejs2 |
3 |
yarn add @babel/runtime-corejs3 |
By default, @babel/ plugin-transform-Runtime will only take the content of the WHATWG specification that is stable or the CONTENT of the ES specification, but it can be specified through the corejs.proposals configuration item that it has not yet adopted.
Note: @babel/plugin-transform-runtime and @babel/preset-env both have corejs configuration items, don’t confuse them, and don’t set them at the same time, otherwise it will clash.
module.exports = {
module: {
rules: [{test: /\.m? js$/,
exclude: /(node_modules)/,
loader: 'babel-loader'.options: {
presets: ['@babel/preset-env'].plugins: [['@babel/plugin-transform-runtime',
{
corejs: {
version: 3.proposals: true,},},],],},},},};Copy the code