Skip to content

Commit

Permalink
feat(nuxi): cli wrapper for self restart (#18641)
Browse files Browse the repository at this point in the history
  • Loading branch information
antfu committed Mar 3, 2023
1 parent 78f1c33 commit db5ea91
Show file tree
Hide file tree
Showing 9 changed files with 75 additions and 4 deletions.
2 changes: 1 addition & 1 deletion docs/3.api/4.advanced/1.hooks.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ Hook | Arguments | Description
`kit:compatibility` | `compatibility, issues` | Allows extending compatibility checks.
`ready` | `nuxt` | Called after Nuxt initialization, when the Nuxt instance is ready to work.
`close` | `nuxt` | Called when Nuxt instance is gracefully closing.
`restart` | - | Called to restart the current Nuxt instance. **This hook is currently only available on the [Edge Channel](/docs/guide/going-further/edge-channel/).** <!-- stabilityedge -->
`restart` | `{ hard?: boolean }` | To be called to restart the current Nuxt instance. **This hook is currently only available on the [Edge Channel](/docs/guide/going-further/edge-channel/).** <!-- stabilityedge -->
`modules:before` | - | Called during Nuxt initialization, before installing user modules.
`modules:done` | - | Called during Nuxt initialization, after installing user modules.
`app:resolve` | `app` | Called after resolving the `app` instance.
Expand Down
3 changes: 1 addition & 2 deletions packages/nuxi/bin/nuxi.mjs
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
#!/usr/bin/env node
process._startTime = Date.now()
import('../dist/cli.mjs').then(r => (r.default || r).main())
import('../dist/cli-wrapper.mjs')
2 changes: 2 additions & 0 deletions packages/nuxi/build.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ export default defineBuildConfig({
},
entries: [
'src/cli',
'src/cli-run',
'src/cli-wrapper',
'src/index'
],
externals: [
Expand Down
4 changes: 4 additions & 0 deletions packages/nuxi/src/cli-run.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// @ts-ignore
process._startTime = Date.now()
// @ts-ignore
import('./cli').then(r => (r.default || r).main())
40 changes: 40 additions & 0 deletions packages/nuxi/src/cli-wrapper.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/**
* 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'

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') {
await startSubprocess([], args)
} else {
await import(cliEntry)
}
9 changes: 9 additions & 0 deletions packages/nuxi/src/commands/dev.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ 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({
Expand Down Expand Up @@ -89,6 +90,14 @@ 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))

if (!isRestart) {
Expand Down
11 changes: 11 additions & 0 deletions packages/nuxi/src/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/**
* 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
1 change: 1 addition & 0 deletions packages/nuxi/src/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export * from './run'
export * from './constants'
7 changes: 6 additions & 1 deletion packages/schema/src/types/hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,12 @@ export interface NuxtHooks {
* Called to restart the current Nuxt instance.
* @returns Promise
*/
'restart': () => HookResult
'restart': (options?: {
/**
* Try to restart the whole process if supported
*/
hard?: boolean
}) => HookResult

/**
* Called during Nuxt initialization, before installing user modules.
Expand Down

0 comments on commit db5ea91

Please sign in to comment.