diff --git a/packages/vite/src/node/cli.ts b/packages/vite/src/node/cli.ts
index b520b9b5144b46..58aa57db02a3eb 100644
--- a/packages/vite/src/node/cli.ts
+++ b/packages/vite/src/node/cli.ts
@@ -169,6 +169,7 @@ cli
'--force',
`[boolean] force the optimizer to ignore the cache and re-bundle`,
)
+ .option('--watchStdin', `[boolean] watch stdin and exit on EOF`)
.action(async (root: string, options: ServerOptions & GlobalCLIOptions) => {
filterDuplicateOptions(options)
// output structure is preserved even after bundling so require()
@@ -364,6 +365,7 @@ cli
.option('--strictPort', `[boolean] exit if specified port is already in use`)
.option('--open [path]', `[boolean | string] open browser on startup`)
.option('--outDir
', `[string] output directory (default: dist)`)
+ .option('--watchStdin', `[boolean] watch stdin and exit on EOF`)
.action(
async (
root: string,
@@ -373,6 +375,7 @@ cli
open?: boolean | string
strictPort?: boolean
outDir?: string
+ watchStdin?: boolean
} & GlobalCLIOptions,
) => {
filterDuplicateOptions(options)
@@ -392,6 +395,7 @@ cli
strictPort: options.strictPort,
host: options.host,
open: options.open,
+ watchStdin: options.watchStdin,
},
})
server.printUrls()
diff --git a/packages/vite/src/node/http.ts b/packages/vite/src/node/http.ts
index ec1bf5e645641d..89560162811c99 100644
--- a/packages/vite/src/node/http.ts
+++ b/packages/vite/src/node/http.ts
@@ -67,6 +67,10 @@ export interface CommonServerOptions {
* Specify server response headers.
*/
headers?: HttpServerHeaders
+ /**
+ * Watch stdin and exit on EOF
+ */
+ watchStdin?: boolean
}
/**
diff --git a/packages/vite/src/node/preview.ts b/packages/vite/src/node/preview.ts
index 2031538cc5c356..38448c1ca6bb5e 100644
--- a/packages/vite/src/node/preview.ts
+++ b/packages/vite/src/node/preview.ts
@@ -60,6 +60,7 @@ export function resolvePreviewOptions(
proxy: preview?.proxy ?? server.proxy,
cors: preview?.cors ?? server.cors,
headers: preview?.headers ?? server.headers,
+ watchStdin: preview?.watchStdin ?? server.watchStdin,
}
}
@@ -153,7 +154,7 @@ export async function preview(
middlewares: app,
httpServer,
async close() {
- teardownSIGTERMListener(closeServerAndExit)
+ teardownSIGTERMListener(config.preview.watchStdin, closeServerAndExit)
await closeHttpServer()
server.resolvedUrls = null
},
@@ -179,7 +180,7 @@ export async function preview(
}
}
- setupSIGTERMListener(closeServerAndExit)
+ setupSIGTERMListener(config.preview.watchStdin, closeServerAndExit)
// apply server hooks from plugins
const postHooks: ((() => void) | void)[] = []
diff --git a/packages/vite/src/node/server/index.ts b/packages/vite/src/node/server/index.ts
index 32a3371cef527b..207a8d270bed1e 100644
--- a/packages/vite/src/node/server/index.ts
+++ b/packages/vite/src/node/server/index.ts
@@ -675,7 +675,7 @@ export async function _createServer(
},
async close() {
if (!middlewareMode) {
- teardownSIGTERMListener(closeServerAndExit)
+ teardownSIGTERMListener(config.server.watchStdin, closeServerAndExit)
}
await Promise.allSettled([
@@ -757,7 +757,7 @@ export async function _createServer(
}
if (!middlewareMode) {
- setupSIGTERMListener(closeServerAndExit)
+ setupSIGTERMListener(config.server.watchStdin, closeServerAndExit)
}
const onHMRUpdate = async (
@@ -1036,6 +1036,7 @@ export const serverConfigDefaults = Object.freeze({
host: 'localhost',
https: undefined,
open: false,
+ watchStdin: false,
proxy: undefined,
cors: true,
headers: {},
diff --git a/packages/vite/src/node/utils.ts b/packages/vite/src/node/utils.ts
index 233f96810da833..d42fe5d684853c 100644
--- a/packages/vite/src/node/utils.ts
+++ b/packages/vite/src/node/utils.ts
@@ -1530,19 +1530,23 @@ export function partialEncodeURIPath(uri: string): string {
}
export const setupSIGTERMListener = (
+ watchStdin: boolean,
callback: (signal?: 'SIGTERM', exitCode?: number) => Promise,
): void => {
process.once('SIGTERM', callback)
- if (process.env.CI !== 'true') {
+ if (watchStdin) {
process.stdin.on('end', callback)
+ // resume stdin to allow the server to exit on EOF
+ process.stdin.resume()
}
}
export const teardownSIGTERMListener = (
- callback: Parameters[0],
+ watchStdin: boolean,
+ callback: Parameters[1],
): void => {
process.off('SIGTERM', callback)
- if (process.env.CI !== 'true') {
+ if (watchStdin) {
process.stdin.off('end', callback)
}
}