refactor(nuxi): hard restart with communication channel (#19423)

This commit is contained in:
pooya parsa 2023-03-03 20:24:49 +01:00 committed by GitHub
parent 3681bddfd5
commit 8fa3fba11f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 44 additions and 54 deletions

View File

@ -1,4 +1,5 @@
// @ts-ignore
process._startTime = Date.now()
// @ts-ignore
import('./cli').then(r => (r.default || r).main())

View File

@ -2,39 +2,38 @@
* This file is used to wrap the CLI entrypoint in a restartable process.
*/
import { fileURLToPath } from 'node:url'
import { execa } from 'execa'
import { EXIT_CODE_RESTART } from './constants'
import { fork } from 'node:child_process'
import type { ChildProcess } from 'node:child_process'
const cliEntry = fileURLToPath(new URL('../dist/cli-run.mjs', import.meta.url))
async function startSubprocess (preArgs: string[], postArgs: string[]) {
const child = await execa(
'node',
[
...preArgs,
cliEntry,
...postArgs
],
{
reject: false,
stdio: 'inherit',
env: {
...process.env,
NUXI_CLI_WRAPPER: 'true'
}
}
)
if (child.exitCode === EXIT_CODE_RESTART) {
await startSubprocess(preArgs, postArgs)
} else {
process.exit(child.exitCode)
}
}
const args = process.argv.slice(2)
// only enable wrapper in dev command
if (args[0] === 'dev') {
startSubprocess([], args)
// Only enable wrapper for nuxt dev command
if (process.argv[2] === 'dev') {
process.env.__CLI_ARGV__ = JSON.stringify(process.argv)
startSubprocess()
} else {
import(cliEntry)
}
function startSubprocess () {
let childProc: ChildProcess
process.on('exit', () => {
if (childProc) {
childProc.kill()
}
})
start()
function start () {
childProc = fork(cliEntry)
childProc.on('close', (code) => { if (code) { process.exit(code) } })
childProc.on('message', (message) => {
if ((message as { type: string })?.type === 'nuxt:restart') {
childProc.kill()
startSubprocess()
}
})
}
}

View File

@ -9,7 +9,7 @@ import { showHelp } from './utils/help'
import { showBanner } from './utils/banner'
async function _main () {
const _argv = process.argv.slice(2)
const _argv = (process.env.__CLI_ARGV__ ? JSON.parse(process.env.__CLI_ARGV__) : process.argv).slice(2)
const args = mri(_argv, {
boolean: [
'no-clear'

View File

@ -14,7 +14,6 @@ import { loadKit } from '../utils/kit'
import { importModule } from '../utils/cjs'
import { overrideEnv } from '../utils/env'
import { writeNuxtManifest, loadNuxtManifest, cleanupNuxtDirs } from '../utils/nuxt'
import { EXIT_CODE_RESTART } from '../constants'
import { defineNuxtCommand } from './index'
export default defineNuxtCommand({
@ -90,15 +89,18 @@ export default defineNuxtCommand({
}
currentNuxt = await loadNuxt({ rootDir, dev: true, ready: false })
// Hard restart
if (process.env.NUXI_CLI_WRAPPER) {
currentNuxt.hooks.hook('restart', (options) => {
if (options?.hard) {
process.exit(EXIT_CODE_RESTART)
}
})
}
currentNuxt.hooks.hookOnce('restart', () => load(true))
currentNuxt.hooks.hookOnce('restart', async (options) => {
if (options?.hard && process.send) {
await listener.close().catch(() => {})
await currentNuxt.close().catch(() => {})
await watcher.close().catch(() => {})
await distWatcher.close().catch(() => {})
process.send({ type: 'nuxt:restart' })
} else {
await load(true)
}
})
if (!isRestart) {
showURL()
@ -121,7 +123,7 @@ export default defineNuxtCommand({
await currentNuxt.ready()
await currentNuxt.hooks.callHook('listen', listener.server, listener)
const address = listener.server.address() as AddressInfo
const address = (listener.server.address() || {}) as AddressInfo
currentNuxt.options.devServer.url = listener.url
currentNuxt.options.devServer.port = address.port
currentNuxt.options.devServer.host = address.address

View File

@ -1,11 +0,0 @@
/**
* Special exit code to restart the process
*
* Usage:
* ```ts
* if (process.env.NUXI_CLI_WRAPPER) {
* process.exit(EXIT_CODE_RESTART)
* }
* ```
*/
export const EXIT_CODE_RESTART = 85

View File

@ -1,2 +1 @@
export * from './run'
export * from './constants'