The hot update of the current project is getting slower and slower, so this article appeared. It is a tutorial article. At present, this set of articles has been introduced into the development environment of the company. There are some differences between the code in this tutorial and the code in the real project. If you want to introduce esbuild package for your company’s project, please leave a comment.

Since the company’s project is an old one, I mainly solved the packaging problem in the development environment, while the production environment is still packaged by Webpack.

Create the basic CRA project

Let’s start by creating a basic React project.

yarn create react-app my-app
Copy the code

Preview folder

After we’ve created the test project, what are the problems that need to be solved to introduce esBuild?

  1. We need a local server to display the packaged files.
  2. You also need a library to parse command-line arguments, passing variables from the development environment.
  3. You also need to delete the last packed file each time you start the project.
  4. You also need to resolve the issue of port numbers.
  5. Solve SVG icon
  6. Introduce esbuild for packaging.

With that out of the way, we’re ready to implement the demo.

Downloading dependency packages

yarn add browser-sync --dev
Copy the code

The main purpose of this package is to create the server, render the packaged files, and listen for file changes in the specified files for esBuild to repackage.

yarn add chalk --dev
Copy the code

The main function of this package is to beautify the character style of the terminal.

yarn add command-line-args --dev
Copy the code

This is a library for parsing command-line arguments, which we use to verify if it is a development environment.

yarn add del --dev
Copy the code

We mainly use this package to delete packaged files or folders.

Yarn add [email protected] - devCopy the code

We use this library mainly to get the port numbers currently available for TCP. I don’t have to install the latest version, because the latest version of the Node. Js have asked, I am v12.18.3 version of Node, the Node and its expected version is: “^ 12.20.0 | | ^ 14.13.1 | | > = 16.0.0”.

Let’s copy the public folder and rename it public-dev. The index.html in this folder is the entry point for our program.

yarn add --dev esbuild-plugin-svgr
Copy the code

Esbuild plugin adds support for importing *.svg files as React components.

yarn add esbuild --dev
Copy the code

Finally, install esBuild.

Modify the package. The json

    "scripts": {
        ...
+++     "dev": "node devBuild.js --dev"
      },
      ...
+++ "type": "module"
Copy the code

Create devBuild. Js

After changing the package.json file, create devbuild.js in the root folder.

import browserSync from "browser-sync"; import chalk from "chalk"; import commandLineArgs from "command-line-args"; import del from "del"; import esbuild from "esbuild"; import getPort from "get-port"; import svgrPlugin from "esbuild-plugin-svgr"; // Create a server. const bs = browserSync.create(); // Destruct the environment variable const {dev} = commandLineArgs({name: "dev", type: Boolean}); Sync ("./public-dev/dist"); // Start esBuild package (async () => {const buildResult = await esbuild.build ({format: "esm", // set the output format of generated JavaScript files. JSX: ["./ SRC /index.jsx"], // outdir: "./public-dev/dist", // output directory chunkNames: "Chunks /[name].[hash]", // incremental: dev, // dev is true because we are listening for changes to files and we want to use esbuild for the development environment: {// This option changes how a given input file is interpreted. ".svg": "text", ".png": "dataURL ",}, bundle: true, // Binding files means inlining any imported dependencies into the file itself. Splitting code currently only applies to ESM output formats. plugins: [svgrPlugin()], inject: ["./public-dev/ react-shimm.js "], // import react as a global variable into esbuild}). Catch ((err) => {console.error(chalk. process.exit(1); }); console.log(chalk.green("The build has finished! 📦 \ n ")); Const port = await getPort({port: getport.makerange (4000, 4999),}); console.log( chalk.cyan( `Launching the Shoelace dev server at http://localhost:${port}! 🥾 \ n `)); // server initializes bs.init({startPath: "/", // initial path port, // port number logLevel: "silent", // logLevel logFileChanges: True, // Log file changes notify: true, // small pop-up notifications in browsers single: true, // provide separate index.html server: {baseDir: "Public-dev ", // base folder index: "index.html", // set server entry file}, files:" SRC /", // listen on files under SRC}); / / to monitor the SRC folder changes bs. Watch (/ SRC/") on (" change ", async (filename) => { console.log(`Source file changed - ${filename}`); Buildresult.rebuild (); }); }) ();Copy the code

index.html

Since I didn’t want to change things directly under the public file, I just copied the public folder and renamed it public-dev. Why do you do that? The main reason is that you don’t want to cross paths with webpack-packed files. So just copy a folder.

In the index. HTML file we’ll introduce packed CSS and JS. Note that you must use ESM to import JS. Otherwise an error will be reported!!

<! DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> <link rel="icon" href="%PUBLIC_URL%/favicon.ico" /> <meta  name="viewport" content="width=device-width, initial-scale=1" /> <meta name="theme-color" content="#000000" /> <meta name="description" content="Web site created using create-react-app" /> <link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" /> <link rel="manifest" href="%PUBLIC_URL%/manifest.json" /> ++ <link rel="stylesheet" type="text/css" href="./dist/index.css" /> <title>React App</title> </head> <body> <noscript>You need to enable JavaScript to run this app.</noscript> <div id="root"></div> ++ <script type="module"> ++ import './dist/index.js' ++ </script> </body> </html>Copy the code

Change the component name suffix to.jsx

react-shim.js

The main purpose of creating this file is to import React as a global variable into esbuild so that you don’t need to import React in every component.

import * as React from "react";
export { React };
Copy the code

Modify the App. JSX

The main thing here is to change the way SVG is used. This is because of the use of the esbuild-plugin-svgr plugin.

It is also crucial to change the suffix of all components from js to JSX.

++ import Logo from "./logo.svg"; import "./App.css"; function App() { return ( <div className="App"> <header className="App-header"> ++ <Logo className="App-logo" /> <p> Edit <code>src/App.js</code> and save to reload. </p> <a className="App-link" href="https://reactjs.org" target="_blank"  rel="noopener noreferrer" > Learn React </a> </header> </div> ); } export default App;Copy the code

At this point, it’s Ok to introduce esbuild into CRA! If you’re interested, give it a try!

Preview the demo

Past wonderful

  • 🔥🔥 Best practices for using WebComponents in React
  • 🔥🔥🔥 How did I optimize the 50+MB APP package file to 4.2MB?
  • Can you explain the principle of Styleds – Components?
  • Interviewer: Can you talk about the difference between extends and a parasitic composite inheritance stereotype?
  • The front end Leader asked me to talk to my colleagues about the event loop
  • React compares the status update mechanism with Vue
  • Do you React to a tree shuttle box?
  • 10 Mistakes to avoid when Using React
  • Webpack Packaging Optimization Direction Guide (Theory)
  • What if VUE encounters drag-and-drop dynamically generated components?
  • JS Coding tips, most people can’t!!
  • TypeScript doesn’t it smell good? Come on!