Package the application for production
mainTo package your application for the local platform you are currently running on, use the package script.
npm run packagerepository·main·Indexed 12 days ago
https://github.com/electron-react-boilerplate/electron-react-boilerplateA production-ready template for building scalable desktop applications using Electron and React. It comes pre-configured with React Router, Webpack, and React Fast Refresh, featuring a secure IPC communication layer via contextBridge and a structured main process entrypoint for lifecycle and window management.
To package your application for the local platform you are currently running on, use the package script.
npm run packageRun the following command to start your application in the dev environment. This typically enables features like React Fast Refresh for a smoother development experience.
npm startTo set up a new project using the Electron React Boilerplate, clone the repository and install the dependencies using npm.
If you encounter issues during installation, refer to the debugging guide.
git clone --depth 1 --branch main https://github.com/electron-react-boilerplate/electron-react-boilerplate.git your-project-name
cd your-project-name
npm installThe boilerplate uses a dynamic path resolution strategy to ensure assets (like icons) are found whether the app is running in development mode or is packaged for production.
process.resourcesPath/assets.../../assets directory relative to the compiled main file.Use the internal getAssetPath helper to retrieve these paths reliably.
const RESOURCES_PATH = app.isPackaged
? path.join(process.resourcesPath, 'assets')
: path.join(__dirname, '../../assets');
const getAssetPath = (...paths: string[]): string => {
return path.join(RESOURCES_PATH, ...paths);
};
// Usage example:
// icon: getAssetPath('icon.png')The src/main/main.ts file serves as the entrypoint for the Electron main process. It is responsible for:
app.whenReady(), window creation, and application shutdown.BrowserWindow instance, configuring its dimensions, icon, and preload scripts.ipcMain to communicate with renderer processes.electron-debug) and installing developer extensions (like REACT_DEVELOPER_TOOLS) when running in a development environment.AppUpdater class to handle background updates via electron-updater.When running npm run build or npm run build:main, this file is compiled to ./src/main.js using webpack.
The renderer process entrypoint (src/renderer/index.tsx) mounts the React application into the DOM element with the ID root. It also demonstrates how to interact with the Electron IPC (Inter-Process Communication) layer via the window.electron object, which is exposed by the preload script.
import { createRoot } from 'react-dom/client';
import App from './App';
const container = document.getElementById('root') as HTMLElement;
const root = createRoot(container);
root.render(<App />);The main process uses ipcMain to listen for messages sent from the renderer process. You can define custom listeners to handle specific events and reply back to the sender.
In this boilerplate, an example listener is provided for the ipc-example channel. It receives an argument, logs it, and replies with a 'pong' message.
import { ipcMain } from 'electron';
ipcMain.on('ipc-example', async (event, arg) => {
const msgTemplate = (pingPong: string) => `IPC test: ${pingPong}`;
console.log(msgTemplate(arg));
event.reply('ipc-example', msgTemplate('pong'));
});The application's UI structure and routing are defined in the App component located in src/renderer/App.tsx. It uses react-router-dom with a MemoryRouter to manage navigation within the Electron renderer process. To add new pages or views, you should define new components and register them as Route elements within the Routes component inside App.
import { MemoryRouter as Router, Routes, Route } from 'react-router-dom';
export default function App() {
return (
<Router>
<Routes>
<Route path="/" element={<Hello />} />
{/* Add new routes here */}
</Routes>
</Router>
);
}The preload script exposes a global electron object to the renderer process via contextBridge. This object provides a secure way to communicate with the Main process using IPC (Inter-Process Communication) without exposing the full ipcRenderer module.
Available methods on window.electron.ipcRenderer:
sendMessage(channel, ...args): Sends a message to the Main process on the specified channel.on(channel, func): Registers a listener for a channel. Returns a cleanup function to remove the listener.once(channel, func): Registers a listener that triggers only once.All channels must be defined in the Channels type (e.g., 'ipc-example').
// Example: Sending a message
window.electron.ipcRenderer.sendMessage('ipc-example', 'hello', 123);
// Example: Listening for messages with cleanup
const unsubscribe = window.electron.ipcRenderer.on('ipc-example', (data) => {
console.log('Received:', data);
});
// Later, to stop listening:
unsubscribe();The boilerplate exposes Electron's ipcRenderer through a window.electron object (provided by the preload script). You can use this to listen for one-time events or send messages to the main process.
Available methods shown in the entrypoint:
window.electron.ipcRenderer.once(channel, callback): Listens for a single occurrence of a specific IPC channel.window.electron.ipcRenderer.sendMessage(channel, args): Sends data to a specific IPC channel.// Listening for a one-time event
window.electron?.ipcRenderer.once('ipc-example', (arg) => {
console.log(arg);
});
// Sending a message
window.electron?.ipcRenderer.sendMessage('ipc-example', ['ping']);