From b68a3a9ce6f261a03e72adf1f628a41ce2998f77 Mon Sep 17 00:00:00 2001 From: erxclau Date: Mon, 9 Jan 2023 22:45:56 -0500 Subject: [PATCH 1/6] feat: use preview server parameter in preview server hook --- packages/vite/src/node/plugin.ts | 5 ++- packages/vite/src/node/preview.ts | 74 ++++++++++++++++++------------- 2 files changed, 46 insertions(+), 33 deletions(-) diff --git a/packages/vite/src/node/plugin.ts b/packages/vite/src/node/plugin.ts index 64b702c2b1b03c..c7c23e9099e17b 100644 --- a/packages/vite/src/node/plugin.ts +++ b/packages/vite/src/node/plugin.ts @@ -91,8 +91,9 @@ export interface Plugin extends RollupPlugin { */ configureServer?: ObjectHook /** - * Configure the preview server. The hook receives the connect server and - * its underlying http server. + * Configure the preview server. The hook receives the {@link PreviewServer} + * instance. This can also be used to store a reference to the server + * for use in other hooks. * * The hooks are called before other middlewares are applied. A hook can * return a post hook that will be called after other middlewares are diff --git a/packages/vite/src/node/preview.ts b/packages/vite/src/node/preview.ts index a9fe3d1894aed8..e96984c6ed207f 100644 --- a/packages/vite/src/node/preview.ts +++ b/packages/vite/src/node/preview.ts @@ -50,6 +50,15 @@ export interface PreviewServer { * The resolved vite config object */ config: ResolvedConfig + /** + * A connect app instance. + * - Can be used to attach custom middlewares to the preview server. + * - Can also be used as the handler function of a custom http server + * or as a middleware in any connect-style Node.js frameworks + * + * https://github.com/senchalabs/connect#use-middleware + */ + middlewares: Connect.Server /** * native Node http server instance */ @@ -66,10 +75,7 @@ export interface PreviewServer { export type PreviewServerHook = ( this: void, - server: { - middlewares: Connect.Server - httpServer: http.Server - }, + server: PreviewServer, ) => (() => void) | void | Promise<(() => void) | void> /** @@ -100,7 +106,15 @@ export async function preview( ) } + const options = config.preview + const logger = config.logger + const app = connect() as Connect.Server + + const hostname = await resolveHostname(options.host) + const port = options.port ?? DEFAULT_PREVIEW_PORT + const protocol = options.https ? 'https' : 'http' + const httpServer = await resolveHttpServer( config.preview, app, @@ -108,10 +122,33 @@ export async function preview( ) setClientErrorHandler(httpServer, config.logger) + const serverPort = await httpServerStart(httpServer, { + port, + strictPort: options.strictPort, + host: hostname.host, + logger, + }) + + const resolvedUrls = await resolveServerUrls( + httpServer, + config.preview, + config, + ) + + const server: PreviewServer = { + config, + middlewares: app, + httpServer, + resolvedUrls, + printUrls() { + printServerUrls(resolvedUrls, options.host, logger.info) + }, + } + // apply server hooks from plugins const postHooks: ((() => void) | void)[] = [] for (const hook of config.getSortedPluginHooks('configurePreviewServer')) { - postHooks.push(await hook({ middlewares: app, httpServer })) + postHooks.push(await hook(server)) } // cors @@ -153,24 +190,6 @@ export async function preview( // apply post server hooks from plugins postHooks.forEach((fn) => fn && fn()) - const options = config.preview - const hostname = await resolveHostname(options.host) - const port = options.port ?? DEFAULT_PREVIEW_PORT - const protocol = options.https ? 'https' : 'http' - const logger = config.logger - - const serverPort = await httpServerStart(httpServer, { - port, - strictPort: options.strictPort, - host: hostname.host, - logger, - }) - - const resolvedUrls = await resolveServerUrls( - httpServer, - config.preview, - config, - ) if (options.open) { const path = typeof options.open === 'string' ? options.open : previewBase @@ -183,12 +202,5 @@ export async function preview( ) } - return { - config, - httpServer, - resolvedUrls, - printUrls() { - printServerUrls(resolvedUrls, options.host, logger.info) - }, - } + return server } From 5cc04df9c225aa5cab47d7e8a6113ff9c4e9d270 Mon Sep 17 00:00:00 2001 From: erxclau Date: Mon, 9 Jan 2023 22:49:46 -0500 Subject: [PATCH 2/6] docs: update `configurePreviewServer` hook docs --- docs/guide/api-javascript.md | 32 ++++++++++++++++++++++++++++++++ docs/guide/api-plugin.md | 5 +++-- 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/docs/guide/api-javascript.md b/docs/guide/api-javascript.md index c66374ae1247e2..460c6ff8149864 100644 --- a/docs/guide/api-javascript.md +++ b/docs/guide/api-javascript.md @@ -198,6 +198,38 @@ import { preview } from 'vite' })() ``` +## `PreviewServer` + +```ts +interface PreviewServer { + /** + * The resolved vite config object + */ + config: ResolvedConfig + /** + * A connect app instance. + * - Can be used to attach custom middlewares to the preview server. + * - Can also be used as the handler function of a custom http server + * or as a middleware in any connect-style Node.js frameworks + * + * https://github.com/senchalabs/connect#use-middleware + */ + middlewares: Connect.Server + /** + * native Node http server instance + */ + httpServer: http.Server + /** + * The resolved urls Vite prints on the CLI + */ + resolvedUrls: ResolvedServerUrls + /** + * Print server urls + */ + printUrls(): void +} +``` + ## `resolveConfig` **Type Signature:** diff --git a/docs/guide/api-plugin.md b/docs/guide/api-plugin.md index 9347c84e6f10e8..263d46bd9ea443 100644 --- a/docs/guide/api-plugin.md +++ b/docs/guide/api-plugin.md @@ -309,10 +309,11 @@ Vite plugins can also provide hooks that serve Vite-specific purposes. These hoo ### `configurePreviewServer` -- **Type:** `(server: { middlewares: Connect.Server, httpServer: http.Server }) => (() => void) | void | Promise<(() => void) | void>` +- **Type:** `(server: PreviewServer) => (() => void) | void | Promise<(() => void) | void>` - **Kind:** `async`, `sequential` +- **See also:** [PreviewServer](./api-javascript#previewserver) - Same as [`configureServer`](/guide/api-plugin.html#configureserver) but for the preview server. It provides the [connect](https://github.com/senchalabs/connect) server and its underlying [http server](https://nodejs.org/api/http.html). Similarly to `configureServer`, the `configurePreviewServer` hook is called before other middlewares are installed. If you want to inject a middleware **after** other middlewares, you can return a function from `configurePreviewServer`, which will be called after internal middlewares are installed: + Same as [`configureServer`](/guide/api-plugin.html#configureserver) but for the preview server. Similarly to `configureServer`, the `configurePreviewServer` hook is called before other middlewares are installed. If you want to inject a middleware **after** other middlewares, you can return a function from `configurePreviewServer`, which will be called after internal middlewares are installed: ```js const myPlugin = () => ({ From f963c903474f6218fcf5db530e43e856ad8bdb90 Mon Sep 17 00:00:00 2001 From: sapphi-red Date: Sat, 25 Mar 2023 17:36:31 +0900 Subject: [PATCH 3/6] feat: use `PreviewServerForHook` and call hook in the previous place --- docs/guide/api-javascript.md | 12 +++++- docs/guide/api-plugin.md | 2 +- packages/vite/src/node/index.ts | 1 + packages/vite/src/node/plugin.ts | 2 +- packages/vite/src/node/preview.ts | 62 +++++++++++++++++-------------- 5 files changed, 47 insertions(+), 32 deletions(-) diff --git a/docs/guide/api-javascript.md b/docs/guide/api-javascript.md index 460c6ff8149864..41086c8d3404df 100644 --- a/docs/guide/api-javascript.md +++ b/docs/guide/api-javascript.md @@ -201,7 +201,15 @@ import { preview } from 'vite' ## `PreviewServer` ```ts -interface PreviewServer { +interface PreviewServer extends PreviewServerForHook { + resolvedUrls: ResolvedServerUrls +} +``` + +## `PreviewServerForHook` + +```ts +interface PreviewServerForHook { /** * The resolved vite config object */ @@ -222,7 +230,7 @@ interface PreviewServer { /** * The resolved urls Vite prints on the CLI */ - resolvedUrls: ResolvedServerUrls + resolvedUrls: ResolvedServerUrls | null /** * Print server urls */ diff --git a/docs/guide/api-plugin.md b/docs/guide/api-plugin.md index 263d46bd9ea443..1bb9e992157fa0 100644 --- a/docs/guide/api-plugin.md +++ b/docs/guide/api-plugin.md @@ -309,7 +309,7 @@ Vite plugins can also provide hooks that serve Vite-specific purposes. These hoo ### `configurePreviewServer` -- **Type:** `(server: PreviewServer) => (() => void) | void | Promise<(() => void) | void>` +- **Type:** `(server: PreviewServerForHook) => (() => void) | void | Promise<(() => void) | void>` - **Kind:** `async`, `sequential` - **See also:** [PreviewServer](./api-javascript#previewserver) diff --git a/packages/vite/src/node/index.ts b/packages/vite/src/node/index.ts index a0e3628484a202..cc44fe17b10524 100644 --- a/packages/vite/src/node/index.ts +++ b/packages/vite/src/node/index.ts @@ -34,6 +34,7 @@ export type { export type { PreviewOptions, PreviewServer, + PreviewServerForHook, PreviewServerHook, ResolvedPreviewOptions, } from './preview' diff --git a/packages/vite/src/node/plugin.ts b/packages/vite/src/node/plugin.ts index c7c23e9099e17b..f2d73cbf1232e0 100644 --- a/packages/vite/src/node/plugin.ts +++ b/packages/vite/src/node/plugin.ts @@ -91,7 +91,7 @@ export interface Plugin extends RollupPlugin { */ configureServer?: ObjectHook /** - * Configure the preview server. The hook receives the {@link PreviewServer} + * Configure the preview server. The hook receives the {@link PreviewServerForHook} * instance. This can also be used to store a reference to the server * for use in other hooks. * diff --git a/packages/vite/src/node/preview.ts b/packages/vite/src/node/preview.ts index e96984c6ed207f..afbcd61e290c83 100644 --- a/packages/vite/src/node/preview.ts +++ b/packages/vite/src/node/preview.ts @@ -45,7 +45,8 @@ export function resolvePreviewOptions( } } -export interface PreviewServer { +// TODO: merge with PreviewServer in Vite 5 +export interface PreviewServerForHook { /** * The resolved vite config object */ @@ -66,16 +67,20 @@ export interface PreviewServer { /** * The resolved urls Vite prints on the CLI */ - resolvedUrls: ResolvedServerUrls + resolvedUrls: ResolvedServerUrls | null /** * Print server urls */ printUrls(): void } +export interface PreviewServer extends PreviewServerForHook { + resolvedUrls: ResolvedServerUrls +} + export type PreviewServerHook = ( this: void, - server: PreviewServer, + server: PreviewServerForHook, ) => (() => void) | void | Promise<(() => void) | void> /** @@ -106,15 +111,7 @@ export async function preview( ) } - const options = config.preview - const logger = config.logger - const app = connect() as Connect.Server - - const hostname = await resolveHostname(options.host) - const port = options.port ?? DEFAULT_PREVIEW_PORT - const protocol = options.https ? 'https' : 'http' - const httpServer = await resolveHttpServer( config.preview, app, @@ -122,26 +119,17 @@ export async function preview( ) setClientErrorHandler(httpServer, config.logger) - const serverPort = await httpServerStart(httpServer, { - port, - strictPort: options.strictPort, - host: hostname.host, - logger, - }) - - const resolvedUrls = await resolveServerUrls( - httpServer, - config.preview, - config, - ) - - const server: PreviewServer = { + const server: PreviewServerForHook = { config, middlewares: app, httpServer, - resolvedUrls, + resolvedUrls: null, printUrls() { - printServerUrls(resolvedUrls, options.host, logger.info) + if (server.resolvedUrls) { + printServerUrls(server.resolvedUrls, options.host, logger.info) + } else { + throw new Error('cannot print server URLs before server is listening.') + } }, } @@ -190,6 +178,24 @@ export async function preview( // apply post server hooks from plugins postHooks.forEach((fn) => fn && fn()) + const options = config.preview + const logger = config.logger + const hostname = await resolveHostname(options.host) + const port = options.port ?? DEFAULT_PREVIEW_PORT + const protocol = options.https ? 'https' : 'http' + + const serverPort = await httpServerStart(httpServer, { + port, + strictPort: options.strictPort, + host: hostname.host, + logger, + }) + + server.resolvedUrls = await resolveServerUrls( + httpServer, + config.preview, + config, + ) if (options.open) { const path = typeof options.open === 'string' ? options.open : previewBase @@ -202,5 +208,5 @@ export async function preview( ) } - return server + return server as PreviewServer } From 879bfedadf8c502851de3b69b38b1485342a0f0b Mon Sep 17 00:00:00 2001 From: sapphi-red Date: Sat, 25 Mar 2023 17:39:59 +0900 Subject: [PATCH 4/6] docs: tweak docs --- docs/guide/api-plugin.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/guide/api-plugin.md b/docs/guide/api-plugin.md index 1bb9e992157fa0..d5f92bad9ad879 100644 --- a/docs/guide/api-plugin.md +++ b/docs/guide/api-plugin.md @@ -311,7 +311,7 @@ Vite plugins can also provide hooks that serve Vite-specific purposes. These hoo - **Type:** `(server: PreviewServerForHook) => (() => void) | void | Promise<(() => void) | void>` - **Kind:** `async`, `sequential` -- **See also:** [PreviewServer](./api-javascript#previewserver) +- **See also:** [PreviewServerForHook](./api-javascript#previewserverforhook) Same as [`configureServer`](/guide/api-plugin.html#configureserver) but for the preview server. Similarly to `configureServer`, the `configurePreviewServer` hook is called before other middlewares are installed. If you want to inject a middleware **after** other middlewares, you can return a function from `configurePreviewServer`, which will be called after internal middlewares are installed: From 8843a2f5767572bf7a1eb55a32a0ae50e7a50fc3 Mon Sep 17 00:00:00 2001 From: sapphi-red Date: Sat, 25 Mar 2023 17:40:36 +0900 Subject: [PATCH 5/6] chore: reduce diff --- packages/vite/src/node/preview.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/vite/src/node/preview.ts b/packages/vite/src/node/preview.ts index afbcd61e290c83..47b9ccf69a5801 100644 --- a/packages/vite/src/node/preview.ts +++ b/packages/vite/src/node/preview.ts @@ -179,10 +179,10 @@ export async function preview( postHooks.forEach((fn) => fn && fn()) const options = config.preview - const logger = config.logger const hostname = await resolveHostname(options.host) const port = options.port ?? DEFAULT_PREVIEW_PORT const protocol = options.https ? 'https' : 'http' + const logger = config.logger const serverPort = await httpServerStart(httpServer, { port, From 57dee72804fd391fb4d08ded17f8230e69791a8c Mon Sep 17 00:00:00 2001 From: sapphi-red Date: Sat, 25 Mar 2023 17:50:47 +0900 Subject: [PATCH 6/6] chore: reorder declaration --- packages/vite/src/node/preview.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/vite/src/node/preview.ts b/packages/vite/src/node/preview.ts index 47b9ccf69a5801..db827a65f5fe51 100644 --- a/packages/vite/src/node/preview.ts +++ b/packages/vite/src/node/preview.ts @@ -119,6 +119,9 @@ export async function preview( ) setClientErrorHandler(httpServer, config.logger) + const options = config.preview + const logger = config.logger + const server: PreviewServerForHook = { config, middlewares: app, @@ -178,11 +181,9 @@ export async function preview( // apply post server hooks from plugins postHooks.forEach((fn) => fn && fn()) - const options = config.preview const hostname = await resolveHostname(options.host) const port = options.port ?? DEFAULT_PREVIEW_PORT const protocol = options.https ? 'https' : 'http' - const logger = config.logger const serverPort = await httpServerStart(httpServer, { port,