introduction
This post has been transferred to my blog. You can read the latest version here:
How to create an electron-forge project with React, Typescript and HMR
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"
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 !
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 !
Hope it helps !
Top comments (12)
Thank you so much, this is very helpful!
However, do you have any idea how to use images and static assets (like fonts) in the app? Trying to import them just doesn't work, and I can't seem to get copy-webpack-plugin to work either.
Thanks for the setup walkthrough. As I followed your steps, I encountered error when adding line:
import App from './App';
and the error was :
Unable to resolve path to module './App' .(import/no-unresolved).
After some digging and googling I found the solution here: stackoverflow.com/questions/598258...
adding :
'settings': {
'import/resolver': {
'typescript': {},
},
},
to .eslintrc.json worked.
Very helpful! I have not been able to get hot reloading to work, however. You say to use .babelrc, but in my hands the webpack-typescript template uses 'ts-loader' not 'babel-loader' by default. Even after changing the loader, however, I have not been able to get this to work.
that was nice walkthrough
Thanks for the tutorial!
Tks !!!!
Thanks for the walkthrough.
At the step with the entryPoints, it is not in the package.json - it is in the forge.config.ts
This was a helpful walkthrough, many thanks
Very helpful! Many thanks.
Thank you working fine