Vite Entry Points for Electron Windows in escrcpy: Multi-Page Build Guide
escrcpy uses a single Vite configuration in desktop/vite.config.js to define multiple HTML entry points for each Electron window, enabling separate builds for the main application, control, explorer, and terminal interfaces.
The escrcpy project leverages Vite’s multi-page build capabilities to manage a complex Electron application architecture with multiple renderer windows. By centralizing the build configuration in desktop/vite.config.js, the repository maintains consistent tooling across all window types while allowing each interface to be built, hot-reloaded, and packaged independently. This approach creates a multi-page build through the rolldownOptions.input configuration, generating distinct HTML outputs for every window the main process can load.
Understanding the Multi-Page Vite Configuration
The configuration file at desktop/vite.config.js serves as the central build orchestrator for the entire desktop application. It defines all entry points—both for renderer processes and Electron’s main process—within a single configuration object that shares common settings via mergeCommon. When Vite runs, it processes each entry point into separate bundles, outputting them to the dist-electron/ directory for the production build.
Renderer Process Entry Points
escrcpy defines four distinct renderer entry points, each corresponding to a specific Electron window type. These are configured in the build.rolldownOptions.input section of the Vite config.
Main Application Window
The default application window loads from the project root HTML file:
- Entry:
index.html(referenced atvite.config.js:65) - Output:
dist-electron/index.html
Control Window (Device Control UI)
This window provides the interface for controlling connected Android devices:
- Entry:
pages/control/index.html(referenced atvite.config.js:66) - Output:
dist-electron/control.html
Explorer Window (File Explorer UI)
The file explorer interface allows browsing device filesystems:
- Entry:
pages/explorer/index.html(referenced atvite.config.js:67) - Output:
dist-electron/explorer.html
Terminal Window (Embedded Shell)
This provides an embedded terminal interface for shell access:
- Entry:
pages/terminal/index.html(referenced atvite.config.js:68) - Output:
dist-electron/terminal.html
Main Process and Preload Script Entries
In addition to renderer entries, the same Vite configuration builds the Electron main process and preload script:
| Process | Vite Entry | Configuration Location |
|---|---|---|
| Main (Electron’s entry point) | electron/main.js |
vite.config.js:20 |
| Preload (exposes safe APIs to renderers) | electron/preload.js |
vite.config.js:29 |
The preload script entry is particularly critical for security, as it builds the script that safely exposes Node.js and Electron APIs to the renderer processes through context isolation.
How the Main Process Loads Vite-Built Windows
When the application starts, the main process loads the appropriate HTML file for each window using the file:// protocol. The windowManager.createWindow() function in desktop/electron/main.js references the built HTML outputs in dist-electron/:
// desktop/electron/main.js (simplified)
await windowManager.createWindow({
name: 'control',
url: `file://${path.resolve('dist-electron/control.html')}`,
});
This architecture decouples the window definitions from the build process—the main process simply loads whatever HTML bundles Vite produces in the output directory.
Development and Production Workflows
Running the Development Server
During development, Vite serves the renderer bundles on port 1535, enabling hot module replacement for all window types:
pnpm dev # launches Vite dev server (port 1535) and Electron
The dev server simultaneously watches the main process and preload script entries, restarting Electron when those change.
Building for Production
The production build generates separate HTML files for each entry point under dist-electron/:
pnpm build # => dist-electron/
# ├─ index.html (main window)
# ├─ control.html (control window)
# ├─ explorer.html (explorer window)
# └─ terminal.html (terminal window)
Each HTML file includes the properly bundled JavaScript and CSS assets for that specific window.
Extending the Configuration: Adding New Windows
To add a new window type to escrcpy, you must define both the Vite entry point and the main process window creation logic.
Step 1: Add the entry to desktop/vite.config.js:
build: {
rolldownOptions: {
input: {
...,
copilot: resolve('pages/copilot/index.html'), // new window entry
},
},
}
Step 2: Open the window from the main process in desktop/electron/main.js:
await windowManager.createWindow({
name: 'copilot',
url: `file://${path.resolve('dist-electron/copilot.html')}`,
});
This pattern maintains the modular architecture while extending the application's window ecosystem.
Summary
- escrcpy configures four renderer entry points (main, control, explorer, terminal) and two Electron process entries (main, preload) in
desktop/vite.config.js - The multi-page build outputs separate HTML files to
dist-electron/for each window type, renamed from their original paths - The main process loads windows via the
file://protocol, pointing to the built HTML entries in the distribution directory - New windows require adding entries to the
rolldownOptions.inputconfiguration and correspondingwindowManager.createWindow()calls
Frequently Asked Questions
How many renderer entry points does escrcpy define in its Vite configuration?
escrcpy defines four renderer entry points in desktop/vite.config.js: the main window at index.html (line 65), plus the control (line 66), explorer (line 67), and terminal (line 68) windows under pages/. Each entry corresponds to a distinct Electron window type with its own HTML output.
Where does escrcpy configure the Electron main process entry point?
The main process entry point is configured at line 20 of desktop/vite.config.js, pointing to electron/main.js. This entry builds the Node.js process that manages window creation, lifecycle events, and native system integration.
What is the purpose of the preload script entry in escrcpy's Vite config?
The preload script entry at line 29 of desktop/vite.config.js builds electron/preload.js, which securely exposes selected Node.js and Electron APIs to renderer processes through context isolation. This follows Electron security best practices by preventing direct access to Node.js from renderer contexts.
How do I add a custom window to escrcpy without breaking the existing build?
Add a new entry to build.rolldownOptions.input in desktop/vite.config.js pointing to your new HTML file (e.g., pages/custom/index.html), then instantiate the window in desktop/electron/main.js using windowManager.createWindow() with the corresponding dist-electron/ HTML output path. The existing mergeCommon configuration ensures your new entry inherits all shared aliases and plugins automatically.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →