DEV Community

Artem Golendukhin
Artem Golendukhin

Posted on

React on esbuild

Usually we use create-react-app which does some magic behind the scenes like Webpack. Webpack is annoying, so let’s see how the app can work without it. I’ll try esbuild in this article instead.

We only need 3 packages:

yarn add react esbuild typescript
Enter fullscreen mode Exit fullscreen mode

React is for components rendering

and esbuild to do all the magic instead of Webpack:

  • Transform jsx to JavaScript
  • Transform Typescript to JavaScript
  • Bundling all our code and node modules to one file
  • Simple http server to serve bundled index.js

So we don’t even need babel. I like babel, but esbuild already handles code transformation for us.

First of all let’s compile a command to use on yarn start:

./node_modules/.bin/esbuild index.tsx --bundle --outdir=. --servedir=. --loader:.js=tsx --watch
Enter fullscreen mode Exit fullscreen mode

Where
—watch - to watch for changes so live reload is possible
--loader:.js=tsx - so esbuild understands and transforms Typescript
--outdir=. --servedir=. - to use a local esbuild http server. “.” - current path

Now let’s make index.html. We only need some basic structure inside:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Minimal Example</title>
</head>
<body>
  <div id="app"></div>
  <script src="index.js"></script>
</body>
</html>
Enter fullscreen mode Exit fullscreen mode

So we can try to write some code:
App.tsx:

import React from 'react';

class App extends React.Component {
  render() {
    return (
      <div>
      </div>
    );
  }
}

React.render(<App />, document.body);
Enter fullscreen mode Exit fullscreen mode

If we want to enable live reloading we also need this line in App.tsx:

new EventSource('/esbuild').addEventListener('change', () => location.reload())
Enter fullscreen mode Exit fullscreen mode

The next step is to check if bundling works as expected. Let’s add a component in a separate file.
Final code:
App.tsx:

import React from 'react';
import { Name } from './components/Name';

new EventSource('/esbuild').addEventListener('change', () => location.reload())

class App extends React.Component {
  render() {
    return (
      <div>
        <h1><Name name="Artem"></Name></h1>
      </div>
    );
  }
}

React.render(<App />, document.body);
Enter fullscreen mode Exit fullscreen mode

components/Name.tsx:

import React from 'react';

type TName = 'Artem' | 'Vlad' | 'Ivan';

interface NameProps {
  name: TName;
}

class Name extends React.Component<NameProps> {
  render() {
    return <div>Hello from {this.props.name}</div>
  }
}

export { Name };
Enter fullscreen mode Exit fullscreen mode

At last we can run the code to see how it works:

yarn start
// ./node_modules/.bin/esbuild index.tsx --bundle --outdir=. --servedir=. --loader:.js=tsx --watch
Enter fullscreen mode Exit fullscreen mode

Hello from Artem

Top comments (0)