This is the fourth day of my participation in the August Text Challenge.More challenges in August

We rarely touch Babel directly during development, but Babel is an integral part of front-end development.

Especially when we want to use ES6+ syntax and TypeScript, we all need Babel.

Babel profile

Babel is a toolchain for older browsers or to ease the conversion of ECMAScript 2015+ code to backward-compatible versions of JavaScript

Including: syntax conversion, source code conversion, Polyfill to achieve the goal to alleviate the missing features, etc

Babel uses a microkernel architecture, meaning that Babel only provides the core architecture @babel/core

@babel/core, like PostCSS, can do very little or nothing at all

If we need to use Babel’s transformation capabilities, then we need to add plug-ins or presets for Babel

Used at the command line

#@babel/core: the core code of Babel, must be installed
#Babel /cli: allows us to use Babel at the command line
npm install @babel/cli @babel/core
Copy the code
 #Use Babel to process our source code
 #SRC: indicates the directory of the source file
 #--out-dir: Specifies the folder dist to output
 #NPX Babel < source file or folder path > --out-dir < output folder >
 npx babel src --out-dir dist
Copy the code

At this point, Babel doesn’t give us any code to convert, that is, the code is basically the same

So if we need a transformation, we can configure plugins for Babel

#@babel/plugin-transform-arrow-functions ==> convert arrow functions
#@babel/plugin-transform-block-scoping ===> Const andletIs converted to a var
npm install @babel/plugin-transform-arrow-functions  @babel/plugin-transform-block-scoping -D
Copy the code
#The conversion uses multiple plug-ins separated by commas (no Spaces before and after)
npx babel src --out-dir dist --plugins=@babel/plugin-transform-block-scoping,@babel/plugin-transform-arrow-functions
Copy the code

But if there is too much to convert, setting up and downloading plug-ins one by one can be troublesome, and preset can be used.

Presets are collections of plug-ins

#Install basic Presets
npm install @babel/preset-env -D
Copy the code
#compile
npx babel src --out-dir dist --presets=@babel/preset-env
Copy the code

The underlying principles of Babel

We can think of Babel as a compiler

The core job of a compiler is to convert one source code (native language) into another source code (target language)

The purpose of the Babel compiler is to convert our source code into another source code that the browser can recognize directly

Babel workflow:

  1. Parsing = Parsing the source code to produce an AST
  2. Transformation === => Traversal phase: The corresponding node is applied to the corresponding plug-in to transform the code and forma new AST
  3. Code Generation === => Converts the new AST back to the common Code. At this time, the newly generated Code is the converted Code

babel-loader

#The installation
npm i @babel/core babel-loader -D
Copy the code
// Configure plugins for Babel
module: {
  rules: [{test: /\.js$/,
      use: {
        loader: 'babel-loader'.options: {
          plugins: [
            '@babel/plugin-transform-arrow-functions'.'@babel/plugin-transform-block-scoping'}}}]}Copy the code
// Configure presets for Babel
// Babel automatically uses the plugin used in the default package based on the syntax supported by the browser browserslist
// Common presets are @bebel/preset-env, @babel/preset-typescript, and @babel/preset-react
module: {
    rules: [{test: /\.js$/,
      use: {
        loader: 'babel-loader'.options: {
         presets: [
          '@babel/preset-env'}}}]}Copy the code
module: {
  rules: [{test: /\.js$/,
      use: {
        loader: 'babel-loader'.options: {
          // You can set some parameters for the preset, which are represented by arrays
          // Parameter 1 is the default package, and parameter 2 is the parameter passed to the default package
          // Targets is the target browser that needs to be compatible - the configured targets attribute overrides the configuration in Browserslist
	  // But we generally don't recommend setting it here, instead setting it in Browserslist
          // Because the configuration set in Browserslist can be shared between multiple tools
          presets: [['@babel/preset-env', {
              targets: 'chrome 88'}]}}}]}Copy the code

The configuration file

Babel configuration information can be put in a separate file, Babel provides us with two configuration files to write

  • Json (or.js,.cjs,.mjs) files – can be used directly in Monorepos project subpackages, preferably with Bebel7 and above
  • .babelrc.json(or.babelrc,.js,.cjs,.mjs) files – the earlier configuration methods used were more cumbersome to configure Monorepos projects

Babel.config. js -- located in the project root directory

module.exports = {
  presets: [
    '@babel/preset-env']}Copy the code

webpack.config.js

module: {
  rules: [{test: /\.js$/,
      use: {
        loader: 'babel-loader'}}}]Copy the code

polyfill

Babel can only convert new syntax features by default,

Some new apis (such as Promise, Generator, Symbol, etc., and instance methods such as array.prototype.includes etc.) are not implemented.

To make these new feature apis available in browsers that do not implement them, you need to use Polyfill

So Polyfill is more like a patch to help us use JavaScript better

#The installation 
#Note: these two packages are development dependencies, not production dependencies - their role is to patch the corresponding code in production code
npm install core-js regenerator-runtime --save
Copy the code
module: {
  rules: [{test: /\.js$/.// The code in the package may have been polyfilled. If you patch the code in the package again, there may be code conflicts, so you need to eliminate them
      exclude: /node_modules/,
      use: {
        loader: 'babel-loader'}}}]Copy the code

useBuiltIns

false

// babel.config.js
module.exports = {
  presets: [['@babel/preset-env',
      { / / useBuiltIns can have three options: false | usage | entry - this property is to tell how Babel patch
        useBuiltIns: false // false Do not patch}}]]Copy the code

usage

// The required polyfills are automatically detected based on the language features present in the source code
// This ensures that the number of polyfills in the final package is minimized and the package size is relatively small
module.exports = {
  presets: [['@babel/preset-env',
      {
        useBuiltIns: 'usage'.corejs: 3 // The default version of corejs is 2, but 3 is usually used, so you need to specify it manually
        Corejs: 3.16 (corejs: 3.16.0 => error)}}]]Copy the code
module.exports = {
  presets: [['@babel/preset-env',
      {
        useBuiltIns: 'usage'.corejs: { 
          version: 3.// Set the version number to use corejs
          propsals: true // Set Corejs to support features in the proposal phase during transformation}}]]}Copy the code

entry

// Whenever the target browser needs to support a new feature, I introduce the corresponding Polyfill, whether or not I actually use it in my code
// So the code packaged in this way is relatively large
module.exports = {
  presets: [['@babel/preset-env',
      {
        // This will not work by default,
        // Add 'import 'core-js/stable' to the import file; import 'regenerator-runtime/runtime'
        useBuiltIns: 'entry'}}]]Copy the code
// index.js
import 'core-js/stable
import 'regenerator-runtime/runtime'
Copy the code

Plugin-transform-runtime

We use polyfill, and by default all features added are global

If we’re writing a tool library that needs to use Polyfil, and someone else is using our tool and the tool library adds features through Polyfill that might contaminate their code, You can use the plugin-transform-Runtime, which implements the polyfill function locally

 #The installation
 npm install @babel/plugin-transform-runtime -D
Copy the code

Note: Since we are using Corejs3, we need to install the corresponding library

#Note: This package is a development dependency
npm i @babel/runtime-corejs3
Copy the code
// @babel/plugin-transform-runtime/useBuiltIns
module.exports = {
  plugins: [
    // @babel/plugin-transform-runtime introduces polyfills as usage
    ['@babel/plugin-transform-runtime', {
      corjs: 3}}]]Copy the code

Compile the JSX

 npm i react react-dom
 npm install @babel/preset-react -D
Copy the code
module.exports = {
 presets: [
  '@babel/preset-react']}Copy the code

Compile the TS

#Ts-loader relies on TSC at compile time, so typescript is downloaded as a ts-Loader dependency
npm i ts-loader -D
Copy the code

How typescript is compiled depends on typescript dependency profiles, so you need to create typescript dependency profiles

tsc --init
Copy the code
/ / configuration
module: {
  rules: [{test: /\.ts$/,
      use: 'ts-loader'}}]Copy the code

Ts-loader essentially uses TSC to compile TS code, so TS-Loder downloads typescript as a dependency

But in real development, there is another way to compile TS, which is Preset -typescript for Babel-Loader

Babel-loader itself compiles typescript, so there is no need to install typescript at this point

#The installation 
#Although there is only one plugin @babel/ Tranform-typescript in @babel/preset-typescrip
#However, the possibility of extending other plug-ins in the default package is not ruled out, so the default package is recommended
npm i @babel/preset-typescript -D
Copy the code

webpack.config.js

module: {
  rules: [{test: /\.ts$/,
      exclude: /node_modules/.// To avoid Babel conversion errors, it is recommended not to package files under node_modules
      loader: 'babel-loader'}}]Copy the code

babel.config.js

module.exports = {
 presets: [
  '@babel/preset-typescript']}Copy the code

ts-loader vs preset-typescript

The name of the function
ts-loader 1. Only TS code can be converted to JS code. If the TS code is incorrectly written, an error message will be displayed during compilation

2. No polyfill will be added for compiled code, ES6 code will not be converted by default (need to be configured in tsconfig.json)
babel-loader 1. You can compile TypeScript directly, convert TS to JS, and polyfill

2. There is no type error detection during compilation, which means that babel-Loader does not output errors to the console

So we can use both together in the actual development

webpack.config.js

module: {
  rules: [{test: /\.ts$/,
      exclude: /node_modules/.// Use ts-loader to compile and convert ts
      // Use Babel's code conversion function, but do not use its transformation function for TS code
      use: [
        'babel-loader'.'ts-loader']]}}Copy the code

babel.config.js

module.exports = {
 presets: [['@babel/preset-env', {
    useBuiltIns: 'usage'.corejs: 3}}]]Copy the code