Skip to content

Commit afe61c2

Browse files
committed
fix(hmr): don't load config twice on server restart
1 parent d3a1567 commit afe61c2

File tree

4 files changed

+77
-79
lines changed

4 files changed

+77
-79
lines changed

src/node/cli.ts

Lines changed: 49 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,16 @@
11
import minimist from 'minimist'
22
import c from 'picocolors'
33
import { createLogger, type Logger } from 'vite'
4-
import { build, createServer, serve } from '.'
4+
import {
5+
build,
6+
createServer,
7+
disposeMdItInstance,
8+
resolveConfig,
9+
serve
10+
} from '.'
511
import { version } from '../../package.json'
612
import { init } from './init/init'
13+
import { clearCache } from './markdownToVue'
714
import { bindShortcuts } from './shortcuts'
815

916
if (process.env.DEBUG) {
@@ -40,30 +47,38 @@ if (!command || command === 'dev') {
4047
argv.optimizeDeps = { force: true }
4148
}
4249

50+
let config = await resolveConfig(root, argv).catch(
51+
logErrorAndExit.bind(null, `failed to resolve config. error:`)
52+
)
4353
const createDevServer = async (isRestart = true) => {
44-
const server = await createServer(root, argv, async () => {
54+
const server = await createServer(config, argv, restartServer)
55+
function restartServer() {
4556
if (!restartPromise) {
4657
restartPromise = (async () => {
58+
try {
59+
config = await resolveConfig(root, argv)
60+
} catch (err: any) {
61+
logError(`failed to resolve config. error:`, err)
62+
return
63+
}
64+
disposeMdItInstance()
65+
clearCache()
4766
await server.close()
4867
await createDevServer()
4968
})().finally(() => {
5069
restartPromise = undefined
5170
})
5271
}
53-
5472
return restartPromise
55-
})
73+
}
5674
await server.listen(undefined, isRestart)
5775
logVersion(server.config.logger)
5876
server.printUrls()
59-
bindShortcuts(server, createDevServer)
77+
bindShortcuts(server, restartServer)
6078
}
61-
createDevServer(false).catch((err) => {
62-
createLogger().error(
63-
`${c.red(`failed to start server. error:`)}\n${err.message}\n${err.stack}`
64-
)
65-
process.exit(1)
66-
})
79+
createDevServer(false).catch(
80+
logErrorAndExit.bind(null, `failed to start server. error:`)
81+
)
6782
} else if (command === 'init') {
6883
createLogger().info('', { clear: true })
6984
init(argv.root)
@@ -74,21 +89,30 @@ if (!command || command === 'dev') {
7489
onAfterConfigResolve(siteConfig) {
7590
logVersion(siteConfig.logger)
7691
}
77-
}).catch((err) => {
78-
createLogger().error(
79-
`${c.red(`build error:`)}\n${err.message}\n${err.stack}`
80-
)
81-
process.exit(1)
82-
})
92+
}).catch(logErrorAndExit.bind(null, `build error:`))
8393
} else if (command === 'serve' || command === 'preview') {
84-
serve(argv).catch((err) => {
85-
createLogger().error(
86-
`${c.red(`failed to start server. error:`)}\n${err.message}\n${err.stack}`
87-
)
88-
process.exit(1)
89-
})
94+
serve(argv).catch(
95+
logErrorAndExit.bind(null, `failed to start server. error:`)
96+
)
9097
} else {
91-
createLogger().error(c.red(`unknown command "${command}".`))
92-
process.exit(1)
98+
logErrorAndExit(`unknown command "${command}".`)
9399
}
94100
}
101+
102+
function logErrorAndExit(message: string, err?: any): never {
103+
logError(message, err)
104+
process.exit(1)
105+
}
106+
107+
function logError(message: string, err?: any) {
108+
const logger = createLogger()
109+
logger.error(
110+
[
111+
c.red(message),
112+
err && 'message' in err && err.message,
113+
err && 'stack' in err && err.stack
114+
]
115+
.filter(Boolean)
116+
.join('\n')
117+
)
118+
}

src/node/plugin.ts

Lines changed: 14 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,7 @@ import {
1818
SITE_DATA_REQUEST_PATH,
1919
resolveAliases
2020
} from './alias'
21-
import {
22-
isAdditionalConfigFile,
23-
resolvePages,
24-
resolveUserConfig,
25-
type SiteConfig
26-
} from './config'
27-
import { disposeMdItInstance } from './markdown/markdown'
21+
import { isAdditionalConfigFile, resolvePages, type SiteConfig } from './config'
2822
import {
2923
clearCache,
3024
createMarkdownToVueRenderFn,
@@ -76,7 +70,7 @@ export async function createVitePressPlugin(
7670
ssr = false,
7771
pageToHashMap?: Record<string, string>,
7872
clientJSMap?: Record<string, string>,
79-
recreateServer?: () => Promise<void>
73+
restartServer?: () => Promise<void>
8074
) {
8175
const {
8276
srcDir,
@@ -354,18 +348,6 @@ export async function createVitePressPlugin(
354348
if (this.environment.name !== 'client') return
355349
const relativePath = path.posix.relative(srcDir, file)
356350

357-
if (themeRE.test(relativePath) && type !== 'update') {
358-
siteConfig.themeDir =
359-
type === 'create' ? path.posix.dirname(file) : DEFAULT_THEME_PATH
360-
siteConfig.logger.info(c.green('page reload ') + c.dim(relativePath), {
361-
clear: true,
362-
timestamp: true
363-
})
364-
this.environment.moduleGraph.invalidateAll()
365-
this.environment.hot.send({ type: 'full-reload' })
366-
return []
367-
}
368-
369351
// update pages, dynamicRoutes and rewrites on md file creation / deletion
370352
if (file.endsWith('.md') && type !== 'update') {
371353
await resolvePages(siteConfig)
@@ -387,17 +369,19 @@ export async function createVitePressPlugin(
387369
{ clear: true, timestamp: true }
388370
)
389371

390-
try {
391-
await resolveUserConfig(siteConfig.root, 'serve', 'development')
392-
} catch (err: any) {
393-
siteConfig.logger.error(err)
394-
return
395-
}
372+
return restartServer?.()
373+
}
396374

397-
disposeMdItInstance()
398-
clearCache()
399-
await recreateServer?.()
400-
return
375+
if (themeRE.test(relativePath) && type !== 'update') {
376+
siteConfig.themeDir =
377+
type === 'create' ? path.posix.dirname(file) : DEFAULT_THEME_PATH
378+
siteConfig.logger.info(c.green('page reload ') + c.dim(relativePath), {
379+
clear: true,
380+
timestamp: true
381+
})
382+
this.environment.moduleGraph.invalidateAll()
383+
this.environment.hot.send({ type: 'full-reload' })
384+
return []
401385
}
402386
}
403387
}

src/node/server.ts

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,21 @@
11
import { createServer as createViteServer, type ServerOptions } from 'vite'
2-
import { resolveConfig } from './config'
2+
import { type SiteConfig } from './config'
33
import { createVitePressPlugin } from './plugin'
44

55
export async function createServer(
6-
root: string = process.cwd(),
6+
config: SiteConfig,
77
serverOptions: ServerOptions & { base?: string } = {},
8-
recreateServer?: () => Promise<void>
8+
restartServer: () => Promise<void>
99
) {
10-
const config = await resolveConfig(root)
11-
12-
if (serverOptions.base) {
13-
config.site.base = serverOptions.base
14-
delete serverOptions.base
15-
}
10+
const { base, ...server } = serverOptions
11+
config.site.base = base ?? config.site.base
1612

1713
return createViteServer({
1814
root: config.srcDir,
1915
base: config.site.base,
2016
cacheDir: config.cacheDir,
21-
plugins: await createVitePressPlugin(config, false, {}, {}, recreateServer),
22-
server: serverOptions,
17+
plugins: await createVitePressPlugin(config, false, {}, {}, restartServer),
18+
server,
2319
customLogger: config.logger,
2420
configFile: config.vite?.configFile
2521
})

src/node/shortcuts.ts

Lines changed: 7 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,19 @@
11
import c from 'picocolors'
22
import type { ViteDevServer } from 'vite'
3-
import { disposeMdItInstance } from './markdown/markdown'
4-
import { clearCache } from './markdownToVue'
5-
6-
type CreateDevServer = () => Promise<void>
3+
import type { Awaitable } from './shared'
74

85
export type CLIShortcut = {
96
key: string
107
description: string
118
action(
129
server: ViteDevServer,
13-
createDevServer: CreateDevServer
14-
): void | Promise<void>
10+
restartServer: () => Promise<void>
11+
): Awaitable<void>
1512
}
1613

1714
export function bindShortcuts(
1815
server: ViteDevServer,
19-
createDevServer: CreateDevServer
16+
restartServer: () => Promise<void>
2017
): void {
2118
if (!server.httpServer || !process.stdin.isTTY || process.env.CI) {
2219
return
@@ -59,7 +56,7 @@ export function bindShortcuts(
5956
if (!shortcut) return
6057

6158
actionRunning = true
62-
await shortcut.action(server, createDevServer)
59+
await shortcut.action(server, restartServer)
6360
actionRunning = false
6461
}
6562

@@ -77,15 +74,12 @@ const SHORTCUTS: CLIShortcut[] = [
7774
{
7875
key: 'r',
7976
description: 'restart the server',
80-
async action(server, createDevServer) {
77+
async action(server, restartServer) {
8178
server.config.logger.info(c.green(`restarting server...\n`), {
8279
clear: true,
8380
timestamp: true
8481
})
85-
disposeMdItInstance()
86-
clearCache()
87-
await server.close()
88-
await createDevServer()
82+
await restartServer()
8983
}
9084
},
9185
{

0 commit comments

Comments
 (0)