From 4c142eac27b13c1a53721f81813bee43be08a7d2 Mon Sep 17 00:00:00 2001 From: Eric Lau <44459660+erxclau@users.noreply.github.com> Date: Sat, 25 Mar 2023 07:05:50 -0400 Subject: [PATCH] feat: use preview server parameter in preview server hook (#11647) --- docs/guide/api-javascript.md | 40 ++++++++++++++++++++++ docs/guide/api-plugin.md | 5 +-- packages/vite/src/node/index.ts | 1 + packages/vite/src/node/plugin.ts | 5 +-- packages/vite/src/node/preview.ts | 55 +++++++++++++++++++++---------- 5 files changed, 84 insertions(+), 22 deletions(-) diff --git a/docs/guide/api-javascript.md b/docs/guide/api-javascript.md index c66374ae1247e2..41086c8d3404df 100644 --- a/docs/guide/api-javascript.md +++ b/docs/guide/api-javascript.md @@ -198,6 +198,46 @@ import { preview } from 'vite' })() ``` +## `PreviewServer` + +```ts +interface PreviewServer extends PreviewServerForHook { + resolvedUrls: ResolvedServerUrls +} +``` + +## `PreviewServerForHook` + +```ts +interface PreviewServerForHook { + /** + * 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 | null + /** + * Print server urls + */ + printUrls(): void +} +``` + ## `resolveConfig` **Type Signature:** diff --git a/docs/guide/api-plugin.md b/docs/guide/api-plugin.md index 9347c84e6f10e8..d5f92bad9ad879 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: PreviewServerForHook) => (() => void) | void | Promise<(() => void) | void>` - **Kind:** `async`, `sequential` +- **See also:** [PreviewServerForHook](./api-javascript#previewserverforhook) - 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 = () => ({ 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 64b702c2b1b03c..f2d73cbf1232e0 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 PreviewServerForHook} + * 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..db827a65f5fe51 100644 --- a/packages/vite/src/node/preview.ts +++ b/packages/vite/src/node/preview.ts @@ -45,11 +45,21 @@ export function resolvePreviewOptions( } } -export interface PreviewServer { +// TODO: merge with PreviewServer in Vite 5 +export interface PreviewServerForHook { /** * 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 */ @@ -57,19 +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: { - middlewares: Connect.Server - httpServer: http.Server - }, + server: PreviewServerForHook, ) => (() => void) | void | Promise<(() => void) | void> /** @@ -108,10 +119,27 @@ export async function preview( ) setClientErrorHandler(httpServer, config.logger) + const options = config.preview + const logger = config.logger + + const server: PreviewServerForHook = { + config, + middlewares: app, + httpServer, + resolvedUrls: null, + printUrls() { + if (server.resolvedUrls) { + printServerUrls(server.resolvedUrls, options.host, logger.info) + } else { + throw new Error('cannot print server URLs before server is listening.') + } + }, + } + // 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,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, @@ -166,7 +192,7 @@ export async function preview( logger, }) - const resolvedUrls = await resolveServerUrls( + server.resolvedUrls = await resolveServerUrls( httpServer, config.preview, config, @@ -183,12 +209,5 @@ export async function preview( ) } - return { - config, - httpServer, - resolvedUrls, - printUrls() { - printServerUrls(resolvedUrls, options.host, logger.info) - }, - } + return server as PreviewServer }