mirror of
https://github.com/alex8088/electron-vite.git
synced 2025-10-13 02:12:13 +08:00
feat: restart Electron after main
or preload
update. fix: preload config will error when preload config is a function.
This commit is contained in:
parent
e35552b4b6
commit
f9cfcf9408
29
README.md
29
README.md
@ -18,6 +18,7 @@ English | [简体中文](./README.zh-CN.md)
|
||||
- 📃Main process, renderer process and preload script Vite configuration combined into one file
|
||||
- 📦Preset optimal build configuration
|
||||
- 🚀HMR for renderer processes
|
||||
- 🌈Restart Electron after `main` or `preload` update
|
||||
|
||||
## Usage
|
||||
|
||||
@ -162,7 +163,7 @@ See [vitejs.dev](https://vitejs.dev/config)
|
||||
|
||||
### Config presets
|
||||
|
||||
#### Build options for `main`:
|
||||
#### Build options for `main`
|
||||
|
||||
- **outDir**: `out\main`(relative to project root)
|
||||
- **target**: `node*`, automatically match node target of `Electron`. For example, the node target of Electron 17 is `node16.13`
|
||||
@ -170,7 +171,7 @@ See [vitejs.dev](https://vitejs.dev/config)
|
||||
- **lib.formats**: `cjs`
|
||||
- **rollupOptions.external**: `electron` and all builtin modules
|
||||
|
||||
#### Build options for `preload`:
|
||||
#### Build options for `preload`
|
||||
|
||||
- **outDir**: `out\preload`(relative to project root)
|
||||
- **target**: the same as `main`
|
||||
@ -178,7 +179,7 @@ See [vitejs.dev](https://vitejs.dev/config)
|
||||
- **lib.formats**: `cjs`
|
||||
- **rollupOptions.external**: the same as `main`
|
||||
|
||||
#### Build options for `renderer`:
|
||||
#### Build options for `renderer`
|
||||
|
||||
- **root**: `src\renderer`(relative to project root)
|
||||
- **outDir**: `out\renderer`(relative to project root)
|
||||
@ -235,6 +236,28 @@ export default {
|
||||
}
|
||||
```
|
||||
|
||||
#### How to restart Electron after `main` or `preload` update?
|
||||
|
||||
```js
|
||||
export default defineConfig({
|
||||
main: ({ command }) => ({
|
||||
build: {
|
||||
watch: command === 'serve' ? {} : undefined,
|
||||
// ...
|
||||
},
|
||||
}),
|
||||
preload: ({ command }) => ({
|
||||
build: {
|
||||
watch: command === 'serve' ? {} : undefined,
|
||||
// ...
|
||||
}
|
||||
}),
|
||||
renderer: {
|
||||
// ...
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
## CLI options
|
||||
|
||||
For the full list of CLI options, you can run `npx electron-vite -h` in your project. The flags listed below are only available via the command line interface:
|
||||
|
@ -18,6 +18,7 @@
|
||||
- 📃 统一所有配置,合并到一个文件中
|
||||
- 📦 预设构建配置,无需关注配置
|
||||
- 🚀 支持渲染进程热更新(HMR)
|
||||
- 🌈 支持 `main` 更新后 Electron 重启和 `preload` 更新后重新挂载
|
||||
|
||||
## 用法
|
||||
|
||||
@ -162,7 +163,7 @@ export default defineConfig({
|
||||
|
||||
### 配置预设
|
||||
|
||||
#### `主进程`编译项预设:
|
||||
#### `主进程`编译项预设
|
||||
|
||||
- **outDir**:`out\main`(相对于根目录)
|
||||
- **target**:`node*`,自动匹配 `Electron` 的 `node` 构建目标,如 Electron 17 为 `node16.13`
|
||||
@ -170,7 +171,7 @@ export default defineConfig({
|
||||
- **lib.formats**:`cjs`
|
||||
- **rollupOptions.external**:`electron` 和所有内置 node 模块(如果用户配置了外部模块 ID,将自动合并)
|
||||
|
||||
#### `preload` 脚本编译项预设:
|
||||
#### `preload` 脚本编译项预设
|
||||
|
||||
- **outDir**:`out\preload`(相对于根目录)
|
||||
- **target**:同`主进程`
|
||||
@ -178,7 +179,7 @@ export default defineConfig({
|
||||
- **lib.formats**:`cjs`
|
||||
- **rollupOptions.external**:同`主进程`
|
||||
|
||||
#### `渲染进程`编译项预设:
|
||||
#### `渲染进程`编译项预设
|
||||
|
||||
- **root**:`src\renderer`(相对于根目录)
|
||||
- **outDir**:`out\renderer`(相对于根目录)
|
||||
@ -187,7 +188,7 @@ export default defineConfig({
|
||||
- **polyfillModulePreload**:`false`,不需要为渲染进程 polyfill `Module Preload`
|
||||
- **rollupOptions.external**:同`主进程`
|
||||
|
||||
#### `主进程`和 `preload` 脚本的 `define` 项设置:
|
||||
#### `主进程`和 `preload` 脚本的 `define` 项设置
|
||||
|
||||
在 Web 开发中,Vite 会将 `'process.env.'` 替换为 `'({}).'`,这是合理和正确的。但在 nodejs 开发中,我们有时候需要使用 `process.env` ,所以 `electron-vite` 重新预设全局变量替换,恢复其使用,预设如下:
|
||||
|
||||
@ -235,6 +236,30 @@ export default {
|
||||
}
|
||||
```
|
||||
|
||||
#### 如何支持 `main` 更新后 Electron 重启和 `preload` 更新后重新挂载?
|
||||
|
||||
在 `serve` 命令下,`main` 和 `preload` 脚本更新后,你可能想要让 Electron 重启和 `preload` 重新挂载,你可以在配置中这样做:
|
||||
|
||||
```js
|
||||
export default defineConfig({
|
||||
main: ({ command }) => ({
|
||||
build: {
|
||||
watch: command === 'serve' ? {} : undefined,
|
||||
// ...
|
||||
},
|
||||
}),
|
||||
preload: ({ command }) => ({
|
||||
build: {
|
||||
watch: command === 'serve' ? {} : undefined,
|
||||
// ...
|
||||
}
|
||||
}),
|
||||
renderer: {
|
||||
// ...
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
## 命令行选项
|
||||
|
||||
在项目中,可运行 `npx electron-vite -h` 获得完整的命令行选项列表。下面列出的标志只能通过命令行使用:
|
||||
|
@ -287,7 +287,7 @@ export async function loadConfigFromFile(
|
||||
if (config.preload) {
|
||||
const preloadViteConfig = config.preload
|
||||
preloadConfig = await (typeof preloadViteConfig === 'function' ? preloadViteConfig(configEnv) : preloadViteConfig)
|
||||
if (!isObject(preloadViteConfig)) {
|
||||
if (!isObject(preloadConfig)) {
|
||||
throw new Error(`preload config must export or return an object`)
|
||||
}
|
||||
} else {
|
||||
|
160
src/server.ts
160
src/server.ts
@ -1,70 +1,122 @@
|
||||
import { spawn } from 'child_process'
|
||||
import { createServer as ViteCreateServer, build as viteBuild, createLogger } from 'vite'
|
||||
import { ChildProcessWithoutNullStreams, spawn } from 'child_process'
|
||||
import {
|
||||
createServer as ViteCreateServer,
|
||||
build as viteBuild,
|
||||
createLogger,
|
||||
Logger,
|
||||
ViteDevServer,
|
||||
UserConfig,
|
||||
mergeConfig
|
||||
} from 'vite'
|
||||
import colors from 'picocolors'
|
||||
import { InlineConfig, resolveConfig } from './config'
|
||||
import { ensureElectronEntryFile, getElectronPath, resolveHostname } from './utils'
|
||||
import { PluginHooks } from 'rollup'
|
||||
|
||||
export function createElectron(root?: string, logger?: Logger): ChildProcessWithoutNullStreams {
|
||||
ensureElectronEntryFile(root)
|
||||
const electronPath = getElectronPath()
|
||||
const ps = spawn(electronPath, ['.'])
|
||||
|
||||
ps.stdout.on('data', chunk => {
|
||||
chunk.toString().trim() && logger && logger.info(chunk.toString())
|
||||
})
|
||||
ps.stderr.on('data', chunk => {
|
||||
chunk.toString().trim() && logger && logger.error(chunk.toString())
|
||||
})
|
||||
ps.on('close', process.exit)
|
||||
|
||||
return ps
|
||||
}
|
||||
|
||||
export function build(config: UserConfig, closeBundle?: PluginHooks['closeBundle']): ReturnType<typeof viteBuild> {
|
||||
const watchConfig: UserConfig = {
|
||||
// Enable watch through `electron.vite.config.{ js | ts | mjs }`
|
||||
// build: { watch: {} },
|
||||
plugins: [
|
||||
{
|
||||
name: 'vite:electron-serve-build',
|
||||
closeBundle
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
return viteBuild(mergeConfig(watchConfig, config))
|
||||
}
|
||||
|
||||
export async function createRenderServer(config: UserConfig): Promise<ViteDevServer> {
|
||||
const server = await ViteCreateServer(config)
|
||||
|
||||
if (!server.httpServer) {
|
||||
throw new Error('HTTP server not available')
|
||||
}
|
||||
|
||||
await server.listen()
|
||||
|
||||
const conf = server.config.server
|
||||
const protocol = conf.https ? 'https:' : 'http:'
|
||||
const host = resolveHostname(conf.host)
|
||||
const port = conf.port
|
||||
process.env.ELECTRON_RENDERER_URL = `${protocol}//${host}:${port}`
|
||||
|
||||
const slogger = server.config.logger
|
||||
|
||||
slogger.info(colors.green(`dev server running for the electron renderer process at:\n`), {
|
||||
clear: !slogger.hasWarned
|
||||
})
|
||||
|
||||
server.printUrls()
|
||||
|
||||
return server
|
||||
}
|
||||
|
||||
export async function createServer(inlineConfig: InlineConfig = {}): Promise<void> {
|
||||
const config = await resolveConfig(inlineConfig, 'serve', 'development')
|
||||
if (config.config) {
|
||||
const logger = createLogger(inlineConfig.logLevel)
|
||||
const { main, preload, renderer } = config.config || {}
|
||||
const logger = createLogger(inlineConfig.logLevel)
|
||||
|
||||
const mainViteConfig = config.config?.main
|
||||
if (mainViteConfig) {
|
||||
await viteBuild(mainViteConfig)
|
||||
let server: ViteDevServer | undefined
|
||||
let ps: ChildProcessWithoutNullStreams | undefined
|
||||
|
||||
if (main) {
|
||||
await build(main, () => {
|
||||
logger.info(colors.green(`\nbuild the electron main process successfully`))
|
||||
}
|
||||
|
||||
const preloadViteConfig = config.config?.preload
|
||||
if (preloadViteConfig) {
|
||||
logger.info(colors.gray(`\n-----\n`))
|
||||
await viteBuild(preloadViteConfig)
|
||||
if (ps) {
|
||||
logger.info(colors.green(`\nwaiting for electron to exit...`))
|
||||
|
||||
logger.info(colors.green(`\nbuild the electron preload files successfully`))
|
||||
}
|
||||
ps.removeAllListeners()
|
||||
ps.kill()
|
||||
ps = createElectron(inlineConfig.root, logger)
|
||||
|
||||
const rendererViteConfig = config.config?.renderer
|
||||
if (rendererViteConfig) {
|
||||
logger.info(colors.gray(`\n-----\n`))
|
||||
|
||||
const server = await ViteCreateServer(rendererViteConfig)
|
||||
|
||||
if (!server.httpServer) {
|
||||
throw new Error('HTTP server not available')
|
||||
logger.info(colors.green(`\n🚀 restart electron app...`))
|
||||
}
|
||||
|
||||
await server.listen()
|
||||
|
||||
const conf = server.config.server
|
||||
|
||||
const protocol = conf.https ? 'https:' : 'http:'
|
||||
const host = resolveHostname(conf.host)
|
||||
const port = conf.port
|
||||
process.env.ELECTRON_RENDERER_URL = `${protocol}//${host}:${port}`
|
||||
|
||||
const slogger = server.config.logger
|
||||
|
||||
slogger.info(colors.green(`dev server running for the electron renderer process at:\n`), {
|
||||
clear: !slogger.hasWarned
|
||||
})
|
||||
|
||||
server.printUrls()
|
||||
}
|
||||
|
||||
ensureElectronEntryFile(inlineConfig.root)
|
||||
|
||||
const electronPath = getElectronPath()
|
||||
|
||||
const ps = spawn(electronPath, ['.'])
|
||||
ps.stdout.on('data', chunk => {
|
||||
chunk.toString().trim() && logger.info(chunk.toString())
|
||||
})
|
||||
ps.stderr.on('data', chunk => {
|
||||
chunk.toString().trim() && logger.error(chunk.toString())
|
||||
})
|
||||
ps.on('close', process.exit)
|
||||
|
||||
logger.info(colors.green(`\nstart electron app...`))
|
||||
}
|
||||
|
||||
if (preload) {
|
||||
logger.info(colors.gray(`\n-----\n`))
|
||||
|
||||
await build(preload, () => {
|
||||
logger.info(colors.green(`\nbuild the electron preload files successfully`))
|
||||
|
||||
if (server) {
|
||||
logger.info(colors.green(`\nwaiting for render page to reload...`))
|
||||
|
||||
server.ws.send({ type: 'full-reload' })
|
||||
|
||||
logger.info(colors.green(`\nreload render page successfully`))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
if (renderer) {
|
||||
logger.info(colors.gray(`\n-----\n`))
|
||||
|
||||
server = await createRenderServer(renderer)
|
||||
}
|
||||
|
||||
ps = createElectron(inlineConfig.root, logger)
|
||||
|
||||
logger.info(colors.green(`\n🚀 start electron app...`))
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user