feat: support electron 42

Add Electron 42 to the node/chrome build target tables and lazily
download the electron binary when path.txt is missing on Electron
42+, since the upstream package no longer downloads itself via
postinstall (supply-chain hardening). This mirrors the behavior of
`npx electron`, so users do not need to add a manual `install-electron`
postinstall script.

close #904
This commit is contained in:
younggglcy 2026-05-15 17:02:10 +08:00
parent 31965d2972
commit 4f18a50382
No known key found for this signature in database
2 changed files with 30 additions and 5 deletions

View File

@ -45,6 +45,8 @@
npm i electron-vite -D
```
> **Note:** Starting with [Electron 42](https://www.electronjs.org/blog/electron-42-0), the `electron` package no longer downloads its binary via `postinstall`. You do not need to add an `install-electron` postinstall script — `electron-vite` will download the binary on demand the first time you run `dev`, `build`, or `preview`, mirroring the behavior of `npx electron`.
### Development & Build
In a project where `electron-vite` is installed, you can use `electron-vite` binary directly with `npx electron-vite` or add the npm scripts to your `package.json` file like this:

View File

@ -1,7 +1,9 @@
import path from 'node:path'
import fs from 'node:fs'
import { createRequire } from 'node:module'
import { type ChildProcess, spawn } from 'node:child_process'
import { type ChildProcess, spawn, spawnSync } from 'node:child_process'
import colors from 'picocolors'
import { createLogger } from 'vite'
import { loadPackageData } from './utils'
const _require = createRequire(import.meta.url)
@ -46,20 +48,39 @@ export function supportImportMetaPaths(): boolean {
return parseInt(majorVer) >= 30
}
function installElectronBinary(electronModulePath: string): void {
const installScript = path.join(electronModulePath, 'install.js')
if (!fs.existsSync(installScript)) {
throw new Error(`electron install script not found at ${installScript}, please reinstall the electron package`)
}
createLogger().info(colors.green('Electron binary not found, installing...'))
const result = spawnSync(process.execPath, [installScript], {
stdio: 'inherit',
cwd: electronModulePath
})
if (result.status !== 0) {
throw new Error('Failed to install electron binary')
}
}
export function getElectronPath(): string {
let electronExecPath = process.env.ELECTRON_EXEC_PATH || ''
if (!electronExecPath) {
const electronModulePath = path.dirname(_require.resolve('electron'))
const pathFile = path.join(electronModulePath, 'path.txt')
let executablePath
if (fs.existsSync(pathFile)) {
executablePath = fs.readFileSync(pathFile, 'utf-8')
const readPathFile = (): string | undefined =>
fs.existsSync(pathFile) ? fs.readFileSync(pathFile, 'utf-8') : undefined
let executablePath = readPathFile()
if (!executablePath && parseInt(getElectronMajorVer()) >= 42) {
// Electron 42+ no longer downloads its binary via postinstall (supply-chain hardening).
installElectronBinary(electronModulePath)
executablePath = readPathFile()
}
if (executablePath) {
electronExecPath = path.join(electronModulePath, 'dist', executablePath)
process.env.ELECTRON_EXEC_PATH = electronExecPath
} else {
throw new Error('Electron uninstall')
throw new Error('Electron is not installed')
}
}
return electronExecPath
@ -69,6 +90,7 @@ export function getElectronNodeTarget(): string {
const electronVer = getElectronMajorVer()
const nodeVer = {
'42': '24.15',
'41': '24.14',
'40': '24.14',
'39': '22.20',
@ -102,6 +124,7 @@ export function getElectronChromeTarget(): string {
const electronVer = getElectronMajorVer()
const chromeVer = {
'42': '148',
'41': '146',
'40': '144',
'39': '142',