-
Notifications
You must be signed in to change notification settings - Fork 0
Description
🚀 Feature: Electron Support with Path Routing
Note
It seems that macOS might be working OK after the first navigation. Is Linux working OK-ish as well? Is the lingering of the drive letter only a problem on Windows?
Problem Description
Currently, @wjfe/n-savant works perfectly in Electron with hash routing, but path routing fails in production builds due to how Electron handles file:// protocol URLs.
Development (works fine):
- URL:
http://localhost:5173/about - Router matches: ✅
/about
Electron Production (fails):
- Initial load:
file:///C:/Users/.../app.asar/dist/index.html - After navigation:
file:///C:/about - Router tries to match: ❌
/C:/about(should be/about)
Root Cause
When using file:// protocol, the History API retains OS-specific path segments:
- Windows:
/C:/about(drive letter persists) - macOS:
file:///about(so, working OK?) - Linux: Unknown situation, but most likely same as macOS
Proposed Solution
Add two new configuration options to init():
init({
implicitMode: 'path',
fullHomePath: '/C:/Users/.../app.asar/dist/index.html', // Maps to "/"
persistentRoot: '/C:' // Stripped from all other paths
})Router Logic:
If location.pathname === fullHomePath → treat as "/"
For all other paths → strip persistentRoot prefix
Maybe: Internal navigation → prepend persistentRoot to maintain consistency
What's Needed Outside this Package
Use OS helper functions to determine the values that should be placed in fullHomePath and persistentRoot options.
Prototypes:
getPersistentPathRoot: () => {
if (process.platform === 'win32') {
// Use actual current directory to get real drive
const drive = path.parse(process.cwd()).root
return `/${drive.charAt(0)}:` // Extract just the drive letter
} else {
// Use actual home directory to detect the real path structure
const homeRoot = path.parse(os.homedir()).dir.split('/')[1]
return `/${homeRoot}` // Could be "/Users", "/home", or something else
}
}// For Electron file:// protocol support:
getInitialHomePath: () => {
const basePath = window.location.pathname.substring(0,
window.location.pathname.lastIndexOf('/') + 1)
}This probably warrants the creation of a companion NPM Package, @wjfe/n-savant-electron, which can be used in the preload secure context:
// preload.cts
// Say, we export a function that returns both pieces at the same time.
import { getElectronRoutingPaths } from '@wjfe/n-savant-electron'
contextBridge.exposeInMainWorld('electronAPI', {
routing: getElectronRoutingPaths()
})Then, in main.ts on the web side, we do:
init({
implicitMode: 'path',
...window.electronAPI?.routing
})Benefits
✅ Perfect DX - One-liner setup for Electron users
✅ Cross-platform - Works on Windows, Linux, macOS
✅ Zero breaking changes - Purely additive feature
✅ Clean separation - Core router stays framework agnostic
✅ Path routing in Electron - No need to fall back to hash routing
Alternative Considered
Using hash routing works, and since multi-hash routing would also work just fine, this is purely a superfluous need.