From 3521d97669f79c19542a53913ed9e73ce5b29b8b Mon Sep 17 00:00:00 2001 From: Romuald Brillout Date: Sat, 9 Apr 2022 23:33:08 +0200 Subject: [PATCH] feat: new hook `configurePreviewServer` --- docs/guide/api-plugin.md | 22 ++++++++++++++++++++++ packages/vite/src/node/plugin.ts | 10 ++++++++++ packages/vite/src/node/preview.ts | 19 +++++++++++++++++++ 3 files changed, 51 insertions(+) diff --git a/docs/guide/api-plugin.md b/docs/guide/api-plugin.md index 50353765261e34..53f80d8266c201 100644 --- a/docs/guide/api-plugin.md +++ b/docs/guide/api-plugin.md @@ -305,6 +305,28 @@ Vite plugins can also provide hooks that serve Vite-specific purposes. These hoo Note `configureServer` is not called when running the production build so your other hooks need to guard against its absence. +### `configurePreviewServer` + +- **Type:** `(server: { middlewares: Connect.Server, httpServer: http.Server }) => (() => void) | void | Promise<(() => void) | void>` +- **Kind:** `async`, `sequential` + + Same than [`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: + + ```js + const myPlugin = () => ({ + name: 'configure-preview-server', + configurePreviewServer(server) { + // return a post hook that is called after other middlewares are + // installed + return () => { + server.middlewares.use((req, res, next) => { + // custom handle request... + }) + } + } + }) + ``` + ### `transformIndexHtml` - **Type:** `IndexHtmlTransformHook | { enforce?: 'pre' | 'post', transform: IndexHtmlTransformHook }` diff --git a/packages/vite/src/node/plugin.ts b/packages/vite/src/node/plugin.ts index 354b246dd9f182..3bfe789a299987 100644 --- a/packages/vite/src/node/plugin.ts +++ b/packages/vite/src/node/plugin.ts @@ -13,6 +13,7 @@ import type { IndexHtmlTransform } from './plugins/html' import type { ModuleNode } from './server/moduleGraph' import type { ConfigEnv, ResolvedConfig } from './' import type { HmrContext } from './server/hmr' +import type { PreviewServerHook } from './preview' /** * Vite plugins extends the Rollup plugin interface with a few extra @@ -79,6 +80,15 @@ export interface Plugin extends RollupPlugin { * are applied. Hook can be async functions and will be called in series. */ configureServer?: ServerHook + /** + * Configure the preview server. The hook receives the connect server and + * its underlying http server. + * + * The hooks are called before other middlewares are applied. A hook can + * return a post hook that will be called after other middlewares are + * applied. Hooks can be async functions and will be called in series. + */ + configurePreviewServer?: PreviewServerHook /** * Transform index.html. * The hook receives the following arguments: diff --git a/packages/vite/src/node/preview.ts b/packages/vite/src/node/preview.ts index c00f62a9cb8f0c..3418efc0796dc9 100644 --- a/packages/vite/src/node/preview.ts +++ b/packages/vite/src/node/preview.ts @@ -14,6 +14,7 @@ import corsMiddleware from 'cors' import { proxyMiddleware } from './server/middlewares/proxy' import { resolveHostname } from './utils' import { printCommonServerUrls } from './logger' +import type * as http from 'http' export interface PreviewOptions extends CommonServerOptions {} @@ -53,6 +54,11 @@ export interface PreviewServer { printUrls: () => void } +export type PreviewServerHook = (server: { + middlewares: Connect.Server + httpServer: http.Server +}) => (() => void) | void | Promise<(() => void) | void> + /** * Starts the Vite server in preview mode, to simulate a production deployment * @param config - the resolved Vite config @@ -71,6 +77,16 @@ export async function preview( await resolveHttpsConfig(config.preview?.https, config.cacheDir) ) + // apply server hooks from plugins + const postHooks: ((() => void) | void)[] = [] + for (const plugin of config.plugins) { + if (plugin.configurePreviewServer) { + postHooks.push( + await plugin.configurePreviewServer({ middlewares: app, httpServer }) + ) + } + } + // cors const { cors } = config.preview if (cors !== false) { @@ -95,6 +111,9 @@ export async function preview( }) ) + // apply post server hooks from plugins + postHooks.forEach((fn) => fn && fn()) + const options = config.preview const hostname = resolveHostname(options.host) const port = options.port ?? 4173