-
-
Notifications
You must be signed in to change notification settings - Fork 520
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(plugin-vite): hot-restart 🔥 #3203
Changes from all commits
c09aa2a
474d2f0
e358075
440bec6
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,7 @@ | ||
import { builtinModules } from 'node:module'; | ||
|
||
import type { VitePluginBuildConfig } from '../Config'; | ||
import type { RendererConfigWithServer } from '../VitePlugin'; | ||
import type { Plugin } from 'vite'; | ||
|
||
/** | ||
|
@@ -33,3 +35,48 @@ export function externalBuiltins() { | |
}, | ||
}; | ||
} | ||
|
||
/** | ||
* Hot restart App during development for better DX. | ||
*/ | ||
export function hotRestart( | ||
config: VitePluginBuildConfig, | ||
// For `VitePluginBuildConfig['restart']` callback args. | ||
context: { renderers: RendererConfigWithServer[] } | ||
) { | ||
const restart = () => { | ||
erickzhao marked this conversation as resolved.
Show resolved
Hide resolved
|
||
// https://github.com/electron/forge/blob/v6.1.1/packages/api/core/src/api/start.ts#L204-L211 | ||
process.stdin.emit('data', 'rs'); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @MarshallOfSound pointed out to me that using Ideally, we should instead expose additional start logic from the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Okay! This does seem a little dangerous. 🚨 |
||
}; | ||
// Avoid first start, it's stated by forge. | ||
let isFirstStart: undefined | true; | ||
|
||
return <Plugin>{ | ||
name: '@electron-forge/plugin-vite:hot-restart', | ||
closeBundle() { | ||
if (isFirstStart == null) { | ||
isFirstStart = true; | ||
return; | ||
} | ||
if (config.restart === false) { | ||
return; | ||
} | ||
if (typeof config.restart === 'function') { | ||
// Leave it to the user to decide whether to restart. | ||
config.restart({ | ||
restart, | ||
renderer: context.renderers.map((renderer) => ({ | ||
// 🎯-②: | ||
// Users can decide which Renderer process to refresh according to `config`. | ||
config: renderer.config, | ||
reload() { | ||
renderer.server.ws.send({ type: 'full-reload' }); | ||
}, | ||
})), | ||
}); | ||
} else { | ||
restart(); | ||
} | ||
}, | ||
}; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -15,20 +15,23 @@ describe('ViteConfigGenerator', () => { | |
const generator = new ViteConfigGenerator(config, '', false); | ||
const servers: ViteDevServer[] = []; | ||
|
||
for (const userConfig of await generator.getRendererConfig()) { | ||
for (const { vite: viteConfig } of await generator.getRendererConfig()) { | ||
const viteDevServer = await vite.createServer({ | ||
configFile: false, | ||
...userConfig, | ||
optimizeDeps: { | ||
disabled: true, | ||
}, | ||
...viteConfig, | ||
}); | ||
|
||
await viteDevServer.listen(); | ||
viteDevServer.printUrls(); | ||
// viteDevServer.printUrls(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. question: is this commented out intentionally? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yep! When I run test on my local machine, some verbose log print, so commented it. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could we remove this before we ship it to users then? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The logs removed here are only for the CI test environment and will not affect the production environment. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
No. If others need it, they can add it themselves. |
||
servers.push(viteDevServer); | ||
|
||
// Make suee that `getDefines` in VitePlugin.ts gets the correct `server.port`. (#3198) | ||
const addressInfo = viteDevServer.httpServer!.address() as AddressInfo; | ||
userConfig.server ??= {}; | ||
userConfig.server.port = addressInfo.port; | ||
viteConfig.server ??= {}; | ||
viteConfig.server.port = addressInfo.port; | ||
} | ||
|
||
const define = await generator.getDefines(); | ||
|
@@ -50,15 +53,15 @@ describe('ViteConfigGenerator', () => { | |
renderer: [], | ||
} as VitePluginConfig; | ||
const generator = new ViteConfigGenerator(config, '', true); | ||
const buildConfig = (await generator.getBuildConfig())[0]; | ||
expect(buildConfig).deep.equal({ | ||
const { vite: viteConfig } = (await generator.getBuildConfig())[0]; | ||
expect(viteConfig).deep.equal({ | ||
mode: 'production', | ||
build: { | ||
lib: { | ||
entry: 'foo.js', | ||
formats: ['cjs'], | ||
// shims | ||
fileName: (buildConfig.build?.lib as any)?.fileName, | ||
fileName: (viteConfig.build?.lib as any)?.fileName, | ||
}, | ||
emptyOutDir: false, | ||
outDir: path.join('.vite', 'build'), | ||
|
@@ -67,7 +70,7 @@ describe('ViteConfigGenerator', () => { | |
clearScreen: false, | ||
define: {}, | ||
// shims | ||
plugins: [buildConfig.plugins?.[0]], | ||
plugins: viteConfig.plugins, | ||
} as UserConfig); | ||
}); | ||
|
||
|
@@ -77,8 +80,8 @@ describe('ViteConfigGenerator', () => { | |
} as VitePluginConfig; | ||
const generator = new ViteConfigGenerator(config, '', false); | ||
const configs = await generator.getRendererConfig(); | ||
for (const [index, rendererConfig] of configs.entries()) { | ||
expect(rendererConfig).deep.equal({ | ||
for (const [index, { vite: viteConfig }] of configs.entries()) { | ||
expect(viteConfig).deep.equal({ | ||
mode: 'development', | ||
base: './', | ||
build: { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
export default function booststrap() { | ||
console.log('App bootstrap.'); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this be
renderers
since it's a list of all renderer processes?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about this API design? 🤔
It looks little simper.
Usage
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think @erickzhao means that because this is an array, it would be better to use plural for words.