Skip to content

Commit 5a10a0e

Browse files
committed
Configure Electron Forge packaging with ASAR unpack for all demos (#1387)
This PR configures Electron Forge packaging across all four electron demos (topics, turtle_tf2, manipulator, car) to enable distributable application creation. The key enhancement is the ASAR configuration that unpacks the rclnodejs module, which requires file system access to generated code and native bindings. **Changes:** - Added Electron Forge packaging infrastructure with ASAR unpack configuration for rclnodejs across all demos - Updated dependencies to rclnodejs ^1.8.1 and upgraded Electron/build tools to latest versions - Migrated manipulator demo from CDN-based Three.js to npm package and added GPU rendering workarounds - Added comprehensive packaging documentation to all demo READMEs Fix: #1386
1 parent 7b285c1 commit 5a10a0e

12 files changed

Lines changed: 377 additions & 22 deletions

File tree

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ API documentation is available [online](https://robotwebtools.github.io/rclnodej
9797

9898
## Electron-based Visualization
9999

100-
Create rich, interactive desktop applications using Electron and web technologies like Three.js. Build 3D visualizations, monitoring dashboards, and control interfaces that run on Windows, macOS, and Linux.
100+
Create rich, interactive desktop applications using Electron and web technologies like Three.js. Demos leverage **Electron Forge** for easy packaging on Windows, macOS, and Linux.
101101

102102
| Demo | Description | Screenshot |
103103
| :-----------------------------------------------: | :-----------------------------------------------------------------------------------------------------------------------------------: | :--------------------------------------------------------------: |

electron_demo/car/README.md

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,56 @@ npm run build
7979
npm start
8080
```
8181

82+
## 📦 Packaging for Distribution
83+
84+
You can package the application into a standalone folder using **Electron Forge**.
85+
86+
### 1. Build the Package
87+
88+
Run the following command to create a distributable executable:
89+
90+
```bash
91+
npm run package
92+
```
93+
94+
The output will be located in the `out/` directory.
95+
96+
**Technical Note on ASAR:** We enable ASAR but configure it to **unpack** the `rclnodejs` module. `rclnodejs` (v1.8.1+) requires file system access to generated code and native bindings, so we use the `asar.unpack` configuration in `package.json` to keep `rclnodejs` files accessible on disk while packing the rest of the application.
97+
98+
```json
99+
"config": {
100+
"forge": {
101+
"packagerConfig": {
102+
"asar": {
103+
"unpack": "**/node_modules/rclnodejs/**"
104+
}
105+
}
106+
}
107+
}
108+
```
109+
110+
### 2. Create Installers (Optional)
111+
112+
To create a `.zip` file or other platform-specific installers (deb/rpm), run:
113+
114+
```bash
115+
npm run make
116+
```
117+
118+
**Note**: Creating DEB/RPM installers requires system tools like `dpkg` and `fakeroot`. For ZIP files, you need `zip`.
119+
120+
### 3. Running the Standalone Application
121+
122+
Even as a standalone application, **ROS 2 must be installed and sourced on the target machine** because `rclnodejs` links dynamically to the ROS 2 shared libraries.
123+
124+
```bash
125+
# Source ROS2 environment
126+
source /opt/ros/<your-ros-distro>/setup.bash
127+
128+
# Run the packaged executable
129+
./out/rclnodejs-electron-car-demo-linux-x64/rclnodejs-electron-car-demo
130+
```
131+
82132
![demo screenshot](./car-control-electron.gif)
83133

84134
## 🎮 How to Use

electron_demo/car/package.json

Lines changed: 47 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,10 @@
44
"description": "An Electron application demonstrating car control with joystick using rclnodejs",
55
"main": "main.js",
66
"scripts": {
7-
"start": "electron .",
8-
"rebuild": "electron-rebuild"
7+
"start": "electron-forge start",
8+
"rebuild": "electron-rebuild",
9+
"package": "electron-forge package",
10+
"make": "electron-forge make"
911
},
1012
"keywords": [
1113
"Electron",
@@ -17,10 +19,50 @@
1719
],
1820
"license": "Apache-2.0",
1921
"dependencies": {
20-
"rclnodejs": "^1.0.0"
22+
"rclnodejs": "^1.8.1"
2123
},
2224
"devDependencies": {
23-
"@electron/rebuild": "^3.6.0",
24-
"electron": "^40.0.0"
25+
"@electron-forge/cli": "^7.11.1",
26+
"@electron-forge/maker-deb": "^7.11.1",
27+
"@electron-forge/maker-rpm": "^7.11.1",
28+
"@electron-forge/maker-squirrel": "^7.11.1",
29+
"@electron-forge/maker-zip": "^7.11.1",
30+
"@electron-forge/plugin-auto-unpack-natives": "^7.11.1",
31+
"@electron-forge/plugin-fuses": "^7.11.1",
32+
"@electron/rebuild": "^4.0.3",
33+
"electron": "^40.1.0"
34+
},
35+
"config": {
36+
"forge": {
37+
"packagerConfig": {
38+
"asar": {
39+
"unpack": "**/node_modules/rclnodejs/**"
40+
}
41+
},
42+
"makers": [
43+
{
44+
"name": "@electron-forge/maker-squirrel",
45+
"config": {
46+
"name": "rclnodejs_car_demo"
47+
}
48+
},
49+
{
50+
"name": "@electron-forge/maker-zip",
51+
"platforms": [
52+
"darwin",
53+
"linux"
54+
]
55+
},
56+
{
57+
"name": "@electron-forge/maker-deb",
58+
"config": {}
59+
},
60+
{
61+
"name": "@electron-forge/maker-rpm",
62+
"config": {}
63+
}
64+
],
65+
"plugins": []
66+
}
2567
}
2668
}

electron_demo/manipulator/README.md

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,9 @@ An interactive Electron application demonstrating a two-joint robotic manipulato
4141

4242
## 📜 Available Scripts
4343

44-
- **`npm start`** - Run demo (requires manual ROS2 environment setup)
44+
- **`npm start`** - Launch the application in development mode
45+
- **`npm run package`** - Package the application into a standalone executable folder
46+
- **`npm run make`** - Create platform-specific installers (requires system tools like `zip`, `dpkg`)
4547
- **`npm run rebuild`** - Rebuild native modules after dependency changes
4648

4749
## 🚀 Quick Start
@@ -156,6 +158,56 @@ ros2 topic hz /joint_states
156158
ros2 topic info /joint_states
157159
```
158160

161+
## 📦 Packaging for Distribution
162+
163+
You can package the application into a standalone folder using **Electron Forge**.
164+
165+
### 1. Build the Package
166+
167+
Run the following command to create a distributable executable:
168+
169+
```bash
170+
npm run package
171+
```
172+
173+
The output will be located in the `out/` directory, for example: `out/rclnodejs-manipulator-demo-linux-x64/`.
174+
175+
**Technical Note on ASAR:** We enable ASAR but configure it to **unpack** the `rclnodejs` module. `rclnodejs` (v1.8.1+) requires file system access to generated code and native bindings, so we use the `asar.unpack` configuration in `package.json` to keep `rclnodejs` files accessible on disk while packing the rest of the application.
176+
177+
```json
178+
"config": {
179+
"forge": {
180+
"packagerConfig": {
181+
"asar": {
182+
"unpack": "**/node_modules/rclnodejs/**"
183+
}
184+
}
185+
}
186+
}
187+
```
188+
189+
### 2. Create Installers (Optional)
190+
191+
To create a `.zip` file for distribution, run:
192+
193+
```bash
194+
npm run make
195+
```
196+
197+
**Note**: This will generate a ZIP archive containing the packaged application.
198+
199+
### 3. Running the Standalone Application
200+
201+
Even as a standalone application, **ROS 2 must be installed and sourced on the target machine** because `rclnodejs` links dynamically to the ROS 2 shared libraries.
202+
203+
```bash
204+
# Source ROS2 environment
205+
source /opt/ros/humble/setup.bash
206+
207+
# Run the packaged executable
208+
./out/rclnodejs-manipulator-demo-linux-x64/rclnodejs-manipulator-demo
209+
```
210+
159211
## 🏗️ Architecture
160212

161213
### Main Process (`main.js`)

electron_demo/manipulator/index.html

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,6 @@ <h5>🎯 What to Look For:</h5>
169169
</div>
170170
</div>
171171

172-
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
173172
<script src="renderer.js"></script>
174173
</body>
175174
</html>

electron_demo/manipulator/main.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,11 @@
1313
const { app, BrowserWindow, ipcMain } = require('electron');
1414
const rclnodejs = require('rclnodejs');
1515

16+
// Fix for WebGL/GPU rendering issues on Linux environment
17+
// Forces software rendering (SwiftShader) if hardware acceleration fails
18+
app.commandLine.appendSwitch('ignore-gpu-blocklist');
19+
app.commandLine.appendSwitch('disable-gpu-sandbox');
20+
1621
let mainWindow;
1722
let manipulatorNode;
1823
let jointStatePublisher;

electron_demo/manipulator/package.json

Lines changed: 40 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,10 @@
44
"description": "Electron application demonstrating a two-joint manipulator visualization using rclnodejs and Three.js",
55
"main": "main.js",
66
"scripts": {
7-
"start": "electron .",
8-
"rebuild": "electron-rebuild"
7+
"start": "electron-forge start",
8+
"rebuild": "electron-rebuild",
9+
"package": "electron-forge package",
10+
"make": "electron-forge make"
911
},
1012
"keywords": [
1113
"Electron",
@@ -20,10 +22,43 @@
2022
],
2123
"license": "Apache-2.0",
2224
"dependencies": {
23-
"rclnodejs": "^1.5.1"
25+
"rclnodejs": "^1.8.1",
26+
"three": "^0.182.0"
2427
},
2528
"devDependencies": {
26-
"@electron/rebuild": "^3.7.2",
27-
"electron": "^40.0.0"
29+
"@electron-forge/cli": "^7.11.1",
30+
"@electron-forge/maker-deb": "^7.11.1",
31+
"@electron-forge/maker-rpm": "^7.11.1",
32+
"@electron-forge/maker-squirrel": "^7.11.1",
33+
"@electron-forge/maker-zip": "^7.11.1",
34+
"@electron-forge/plugin-auto-unpack-natives": "^7.11.1",
35+
"@electron-forge/plugin-fuses": "^7.11.1",
36+
"@electron/rebuild": "^4.0.3",
37+
"electron": "^40.1.0"
38+
},
39+
"config": {
40+
"forge": {
41+
"packagerConfig": {
42+
"asar": {
43+
"unpack": "**/node_modules/rclnodejs/**"
44+
}
45+
},
46+
"makers": [
47+
{
48+
"name": "@electron-forge/maker-squirrel",
49+
"config": {
50+
"name": "rclnodejs_manipulator_demo"
51+
}
52+
},
53+
{
54+
"name": "@electron-forge/maker-zip",
55+
"platforms": [
56+
"darwin",
57+
"linux"
58+
]
59+
}
60+
],
61+
"plugins": []
62+
}
2863
}
2964
}

electron_demo/manipulator/renderer.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
const { ipcRenderer } = require('electron');
1414
const process = require('process');
15+
const THREE = require('three');
1516

1617
// Three.js scene components
1718
let scene, camera, renderer, controls;

electron_demo/topics/README.md

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,56 @@ The demo window will open with:
6565
- **Message display area** showing received messages
6666
- **Counters** for published and received messages
6767

68+
## 📦 Packaging for Distribution
69+
70+
You can package the application into a standalone folder using **Electron Forge**.
71+
72+
### 1. Build the Package
73+
74+
Run the following command to create a distributable executable:
75+
76+
```bash
77+
npm run package
78+
```
79+
80+
The output will be located in the `out/` directory.
81+
82+
**Technical Note on ASAR:** We enable ASAR but configure it to **unpack** the `rclnodejs` module. `rclnodejs` (v1.8.1+) requires file system access to generated code and native bindings, so we use the `asar.unpack` configuration in `package.json` to keep `rclnodejs` files accessible on disk while packing the rest of the application.
83+
84+
```json
85+
"config": {
86+
"forge": {
87+
"packagerConfig": {
88+
"asar": {
89+
"unpack": "**/node_modules/rclnodejs/**"
90+
}
91+
}
92+
}
93+
}
94+
```
95+
96+
### 2. Create Installers (Optional)
97+
98+
To create a `.zip` file or other platform-specific installers (deb/rpm), run:
99+
100+
```bash
101+
npm run make
102+
```
103+
104+
**Note**: Creating DEB/RPM installers requires system tools like `dpkg` and `fakeroot`. For ZIP files, you need `zip`.
105+
106+
### 3. Running the Standalone Application
107+
108+
Even as a standalone application, **ROS 2 must be installed and sourced on the target machine** because `rclnodejs` links dynamically to the ROS 2 shared libraries.
109+
110+
```bash
111+
# Source ROS2 environment
112+
source /opt/ros/<your-ros-distro>/setup.bash
113+
114+
# Run the packaged executable
115+
./out/rclnodejs-electron-demo-linux-x64/rclnodejs-electron-demo
116+
```
117+
68118
## 📁 Project Structure
69119

70120
- **`package.json`** - Project configuration and dependencies

0 commit comments

Comments
 (0)