โ€” ยท 4 min read Min read

How to create an electron-forge project with React, TS and HMR

Post Photo by j.mt_photography on Pexels

As a react developer, I've always been used to magic CLIs that scaffold projects with everything included, such as Next.js or create-react-app. I don't think I ever setup react from scratch, but there is no electron-forge template for that, so I had to dig in...

What we want

A buildable electron project that includes :

  • react
  • typescript
  • hot module reloading on the react part

Getting started with the webpack-typescript template

electron-forge provides us a convenient webpack-typescript that generates a boilerplate configured with typescript and webpack support (who would have guessed ?). Create the project using the following command : yarn create electron-app my-new-app --template=typescript-webpack

Once the project has been created, enter it and run the project to ensure it works: cd my-new-app yarn start

The default app should open and display "Hello World" The default app should open and display "Hello World"

Adding react

Now that our app opens properly, we need to add react dependencies. In the terminal, run: yarn add react react-dom @types/react @types/react-dom

That done, replace the content of the body by the div that will contain the react app in src/index.html :

@@ -6,7 +6,6 @@
 
   </head>
   <body>
-    <h1>๐Ÿ’– Hello World!</h1>
-    <p>Welcome to your Electron application.</p>
+    <div id="root"></div>
   </body>
 </html>

Create a file in src called App.tsx and paste the following code into it :

import * as React from 'react';
 
const App = () => <div>Hi from react !</div>;
 
export default App;

To make sure typescript understands jsx, add "jsx": "react" in your tsconfig.json file like so:

@@ -12,7 +12,8 @@
     "resolveJsonModule": true,
     "paths": {
       "*": ["node_modules/*"]
-    }
+    },
+    "jsx": "react"
   },
   "include": [
     "src/**/*"

Now we need to update the renderer to bind react to the div we created earlier. First, rename it from src/renderer.ts to src/renderer.tsx then replace the content by the following:

import './index.css';
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
 
ReactDOM.render(<App />, document.getElementById('root'));

Now update the js entryPoint in package.json with the correct name:

@@ -52,7 +52,7 @@
               "entryPoints": [
                 {
                   "html": "./src/index.html",
-                  "js": "./src/renderer.ts",
+                  "js": "./src/renderer.tsx",
                   "name": "main_window"
                 }
               ]

You can now run yarn start. The application should open and the react app should appear !

The application successfully running react

However, if you try to change some code in the App.tsx, the changes won't appear on your App. We need to manually install a module to hot reload changes.

Adding hot-reload

We're almost there ! Run yarn add react-hot-loader, then head over srx/App.tsx and add the following lines:

@@ -1,5 +1,6 @@
+import { hot } from 'react-hot-loader';
 import * as React from 'react';
 
 const App = () => <div>Hi from react!</div>;
 
-export default App;
\ No newline at end of file
+export default hot(module)(App);
\ No newline at end of file

Now, we need to configure babel to use the react-hot-loader package that will enable hot reloading by creating a .babelrc file at the root of the repository and putting only one line into it :

#.babelrc
{ "plugins": ["react-hot-loader/babel"] }

Finally, run yarn start, change the message, hit save and it should work !

CleanShot 2020-06-14 at 19.30.39.gif

Hope it helps !