preface

The article has translation direction, specific can see the link at the end of the article.

With the official release of ES6, ES2016, ES2017… The steady annual updates, along with new proposals, make JavaScript more mature. But older browsers are not fully compatible with some of the new syntax and apis. Babel is now more than just an ES6 to ES5 syntactic translation tool. It is a specification and ecosystem that helps us work with JavaScript more efficiently.

@ Babel/preset – env

@babel/preset-env is introduced as an alternative to babel-preset- ES2015, and is mainly used to transform the grammars that are already officially included in TC39. Therefore, it cannot process syntax that is still in the proposal. For syntax that is in the stage, the corresponding plugin needs to be installed to process it.

Besides syntactic conversions, another important feature of @babel/preset-env is the handling of polyfills. New additions to the standard library may include syntactic features such as arrow functions, as well as new apis such as Promises, sets, inclues, etc.

For syntax, Babel can do some transformation by generating a static syntax tree to generate the corresponding ES5 code.

But for new apis, browsers need to support them natively, or a lot of code is used to simulate the API. @babel/ Polyfill are the shippers of the API, which are introduced so that older browsers can emulate the implementation of the new API.

Core-js is the core dependency of @babel/ Polyfill, which is now released in version 3.0, and @babel/preset- Env is supported in version 7.4.0. Major releases can cause some disruption, but they also bring many advantages.

Core-js forgotten package

What is the core – js

  • It’s a polyfill of the JavaScript standard library
  • It’s as modular as possible, allowing you to choose the features you want
  • It can not pollute the global space
  • It is highly integrated with Babel to optimize the introduction of Core-JS

Motivation for core-JS upgrades

  • Destructive changes in Core-JS can only be made in major version upgrades
  • The [email protected] version was frozen a year and a half ago, and all new features will only be added to the 3.0 branch

Important changes to core-js@3

  • Core-js is almost fully supported for features already stable in ECMAScript, with some new features introduced in core-js@3
  • Some proposals that have been added to ES2016-ES2019 are now marked as stable features
  • The proposals configuration items are added to support apis in the proposal phase. However, because the proposal phase is unstable, there may be major changes before the standard is formally added, so they need to be used with caution. Some proposals that changed dramatically were updated
  • Added support for web standards such as urls and URLSearchParams
  • Removed some outdated features

Monorepos package split

core-js@2 One of the most common problems is that packages are too large (~2M) and have many duplicate files referenced. For this reason, core-js@3 splits the package, and the three core packages are

  • Core-js: Define global polyfill (~ 500K, 40K minified and gzipped)
  • Core-js-pure: provides polyfill that does not pollute the global environment, equivalent to core-js@2/library (~ 440K)
  • Core-js-compat: Contains the necessary data for core-JS modules and apis. Browserslist generates a list of the required core-JS modules

In previous versions, features that have entered the ECMAScript standard use ES6. Features in the proposal phase are represented by the prefix of ES7. The reason for choosing this prefix is that in 2014, all features after ES6 were considered to be named after ES7.

In the cores-js@3 version, all features in the specification use ES. The feature in the proposal uses the esNext. Prefix.

Almost all CommonJS entry files have been changed. More module entries are included at core-js@3. This allows for more flexibility in on-demand support for the target browser, as well as file size optimizations.

In core-js@2, @babel/preset- EVn has a data-table inside the plugin, which maintains the support of different browsers for specific APIS, and uses this data-table to realize different targets to load the required Core-JS module on demand. Due to some inherent problems with the compat-table, the authors re-maintain a package, core-js-compat, to provide core-JS module information that is not required by the target engine.

const {
  list,              // array of required modules
  targets,           // object with targets for each module
} = require('core-js-compat')({
  targets: '> 2.5%', // browserslist query
  filter: 'es.', // optional filter - string-prefix, regexp or list of modules }); console.log(targets); / * = > {'es.symbol.description': { ios: '12.0-12.1' },
  'es.array.reverse': { ios: '12.0-12.1' },
  'es.string.replace': { firefox: '63', ios: '12.0-12.1' },
  'es.string.trim': { ios: '12.0-12.1' },
  'es.promise': { firefox: '63' },
  'es.promise.finally': { firefox: '63' },
  'es.array-buffer.slice': { ios: '12.0-12.1' },
  'es.typed-array.int8-array': { ios: '12.0-12.1' },
  'es.typed-array.uint8-array': { ios: '12.0-12.1' },
  'es.typed-array.uint8-clamped-array': { ios: '12.0-12.1' },
  'es.typed-array.int16-array': { ios: '12.0-12.1' },
  'es.typed-array.uint16-array': { ios: '12.0-12.1' },
  'es.typed-array.int32-array': { ios: '12.0-12.1' },
  'es.typed-array.uint32-array': { ios: '12.0-12.1' },
  'es.typed-array.float32-array': { ios: '12.0-12.1' },
  'es.typed-array.float64-array': { ios: '12.0-12.1' },
  'es.typed-array.from': { ios: '12.0-12.1' },
  'es.typed-array.of': { ios: '12.0-12.1' }
}
*/
Copy the code

Here are some simple examples of the new entry file at core-js@3

// polyfill all `core-js` features:
import "core-js";
// polyfill only stable `core-js` features - ES and web standards:
import "core-js/stable";
// polyfill only stable ES features:
import "core-js/es";

// if you want to polyfill `Set`:
// all `Set`-related features, with ES proposals:
import "core-js/features/set";
// stable required for `Set` ES features and features from web standards
// (DOM collections iterator in this case):
import "core-js/stable/set";
// only stable ES features required for `Set`:
import "core-js/es/set";
// the same without global namespace pollution:
import Set from "core-js-pure/features/set";
import Set from "core-js-pure/stable/set";
import Set from "core-js-pure/es/set";

// if you want to polyfill just required methods:
import "core-js/features/set/intersection";
import "core-js/stable/queue-microtask";
import "core-js/es/array/from";

// polyfill reflect metadata proposal:
import "core-js/proposals/reflect-metadata";
// polyfill all stage 2+ proposals:
import "core-js/stage/2";
Copy the code

The core – js @ 3 and Babel

As mentioned above, Core-JS is highly integrated with Babel, which makes it possible to load core-JS on demand. core-js@3 is supported in babel7.4.0.

@babel/prest-env

After upgrading to version 7.4.0 or higher, both core-js@2 and core-js@3 are supported. So the corejs configuration was added to control the required version, which is core-js@2 by default and will prompt text output to upgrade to version 3.

@babel/prest-env can load @babel/polyfill based on targets by configuring useBuiltIns.

@ Babel/polyfill changes

@babel/ Polyfill is a simple package that contains core-js and Regenerator-Runtime packages. When core-JS is upgraded to version 3.0, @babel/ Polyfill will be abandoned because it only contains version 2.0 of Core-JS.

So when you upgrade @babel/prest-env to 7.4.0 and use core-js@3, you need to make the following substitution

// install [email protected] and regenerator-Runtime yarn add core-js@3 yarn add regenerator-Runtime // babel.config.js presets: [["@babel/preset-env", {
    useBuiltIns: "entry", // or "usage"Corejs: 3,}]] // index.js // before import"@babel/polyfill";

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

Copy the code

@babel/runtime

When using core-js@3, @babel/ transform-Runtime loads the corresponding polyfill code from core-js-pure. Core-js-pure does not pollute global variables and is suitable for third-party library development.

The latest version of @babel/ transform-Runtime supports core-js@3. Perform the following operations.

yarn remove @babel/runtime-corejs2
yarn add @babel/runtime-corejs3

//babel.config.js
plugins: [
  ["@babel/transform-runtime", {
    corejs: 3,
  }]
]

Copy the code

Change a

In previous versions, the biggest problem with @babel/ Runtime was that methods on instances could not be simulated, such as the includes method on arrays.

But in the core-js@3 version, all instance methods can be polyfilled.

Array. includes(something) ↓ ↓ ↓ ↓ import _includesInstanceProperty from"@babel/runtime-corejs3/core-js-stable/instance/includes";
_includesInstanceProperty(array).call(array, something);

Copy the code

Change the two

core-js@3 supports emulating apis for ECMAScript proposals.

The default configuration of @babel/ plugin-transform-Runtime is not to inject polyfill code for proposals. If you want to support the proposed API, just add a configuration item similar to @babel/preset-env.

plugins: [
  ["@babel/transform-runtime", {
    corejs: { version: 3, proposals: true}}]]Copy the code
new Set([1, 2, 3, 2, 1]); string.matchAll(/something/g); ↓ ↓ ↓ ↓ ↓ // Without any proposals import _Set from"@babel/runtime-corejs3/core-js-stable/set";
new _Set([1, 2, 3, 2, 1]);
string.matchAll(/something/g);


// with proposals: true
import _Set from "@babel/runtime-corejs3/core-js/set";
import _matchAllInstanceProperty from "@babel/runtime-corejs3/core-js/instance/match-all";
new _Set([1, 2, 3, 2, 1]);
_matchAllInstanceProperty(string).call(string, /something/g);

Copy the code

Looking to the future

Support for older browsers

Core-js supports as many browsers and platforms as possible, even IE8- and some older Versions of Firefox. But supporting so many older browsers inevitably causes polyfill files to grow, increasing the size of packages.

The biggest problem comes from some es3-only browsers, such as IE8-. Most of the new ES features are implemented based on ES5 syntax, resulting in a lot of padding code to smooth out the differences between ES5 and ES3 in order to support the new features in older browsers.

While IE8 is still very popular in some regions, some browsers should be allowed to die out for the sake of language development and advancement. core-js@3 has dropped support for IE6, and in the next major release core-js@ will no longer support IE8, and will only support browsers based on ES5 syntax.

ECMAScript module

Core-js modules are based on the CommonJS specification. With the release and popularity of ECMAScript modules, core-JS should provide an alternative version of the ECMAScript module specification.

Better optimizes polyfill loading problems

There are still problems when using useBuiltIns: Usage of @babel/preset-env. For example, when a project’s files cannot be statically analyzed, you need to provide a solution for polyfill loading. Another problem is that useBuiltIns: Usage may inject dozens of core-JS import statements into a file header. When there are hundreds or thousands of files in a project, the injected syntax can take up an objective amount of volume. We need a mechanism to collect all modules that need to be used, de-redo them, and finally inject them into the project.

For developers who need to support older browsers, the size of polyfill files can swell dramatically to support browsers like IE11. One solution is to use the Type = module/nomodules property to generate two different packages, one for modern browsers and one for older browsers, but this is not a perfect solution; Another solution is to provide a polyfill service, which determines the browser model based on the UA in the request and returns the polyfill file required by the browser. A similar service is polyfill. However, the return of polyfill. IO is not accurate and the availability is not very high.

others

  • Add support for Web standards, such as FETCH
  • @babel/ Runtime provides support for the target environment, similar to the targets field in @babel/preset-env

link

core-js

core-js@3, babel and a look into the future

Babel/env 7.4.0 Released: Core-js 3, static Private Methods and Partial Applications