vite
Version:
Native-ESM powered web dev build tool
1,245 lines (1,202 loc) • 144 kB
TypeScript
/// <reference types="node" />
import { ModuleRunnerTransport } from "./moduleRunnerTransport-BWUZBVLX.js";
import { ConnectedPayload, CustomPayload, CustomPayload as hmrPayload_CustomPayload, ErrorPayload, FullReloadPayload, HMRPayload, HotPayload, HotPayload as hmrPayload_HotPayload, PrunePayload, Update, UpdatePayload } from "../../types/hmrPayload.js";
import { CustomEventMap, InferCustomEventPayload, InferCustomEventPayload as hmrPayload_InferCustomEventPayload, InvalidatePayload } from "../../types/customEvent.js";
import * as Rollup from "rollup";
import { CustomPluginOptions, ExistingRawSourceMap, InputOption, InputOptions, LoadResult, MinimalPluginContext, ModuleFormat, ModuleInfo, ObjectHook, OutputBundle, OutputChunk, PartialResolvedId, PluginContext, PluginContextMeta, PluginHooks, ResolveIdResult, RollupError, RollupLog, RollupOptions, RollupOutput, RollupWatcher, SourceDescription, SourceMap, SourceMapInput, TransformPluginContext, WatcherOptions } from "rollup";
import { parseAst, parseAstAsync } from "rollup/parseAst";
import * as http from "node:http";
import { Agent, ClientRequest, ClientRequestArgs, OutgoingHttpHeaders, ServerResponse } from "node:http";
import { Http2SecureServer } from "node:http2";
import * as fs from "node:fs";
import * as events from "node:events";
import { EventEmitter } from "node:events";
import { Server as HttpsServer, ServerOptions as HttpsServerOptions } from "node:https";
import * as net from "node:net";
import * as url from "node:url";
import { URL } from "node:url";
import * as stream from "node:stream";
import { Duplex, DuplexOptions } from "node:stream";
import { FetchFunction, FetchFunctionOptions, FetchResult, FetchResult as moduleRunner_FetchResult, ModuleEvaluator, ModuleRunner, ModuleRunnerHmr, ModuleRunnerOptions } from "vite/module-runner";
import { BuildOptions as esbuild_BuildOptions, TransformOptions as EsbuildTransformOptions, TransformOptions as esbuild_TransformOptions, TransformResult as esbuild_TransformResult, version as esbuildVersion } from "esbuild";
import { SecureContextOptions } from "node:tls";
import { ZlibOptions } from "node:zlib";
import { Terser, TerserMinifyOptions } from "../../types/internal/terserOptions.js";
import * as PostCSS from "postcss";
import { LightningCSSOptions, LightningCSSOptions as lightningcssOptions_LightningCSSOptions } from "../../types/internal/lightningcssOptions.js";
import { LessPreprocessorBaseOptions, SassModernPreprocessBaseOptions, StylusPreprocessorBaseOptions } from "../../types/internal/cssPreprocessorOptions.js";
import { GeneralImportGlobOptions, ImportGlobFunction, ImportGlobOptions, KnownAsTypeMap } from "../../types/importGlob.js";
import { ChunkMetadata, CustomPluginOptionsVite } from "../../types/metadata.js";
//#region src/types/alias.d.ts
interface Alias {
find: string | RegExp;
replacement: string;
/**
* Instructs the plugin to use an alternative resolving algorithm,
* rather than the Rollup's resolver.
* @default null
*/
customResolver?: ResolverFunction | ResolverObject | null;
}
type MapToFunction<T> = T extends Function ? T : never;
type ResolverFunction = MapToFunction<PluginHooks['resolveId']>;
interface ResolverObject {
buildStart?: PluginHooks['buildStart'];
resolveId: ResolverFunction;
}
/**
* Specifies an `Object`, or an `Array` of `Object`,
* which defines aliases used to replace values in `import` or `require` statements.
* With either format, the order of the entries is important,
* in that the first defined rules are applied first.
*
* This is passed to \@rollup/plugin-alias as the "entries" field
* https://github.com/rollup/plugins/tree/master/packages/alias#entries
*/
type AliasOptions = readonly Alias[] | {
[find: string]: string;
};
//#endregion
//#region src/types/anymatch.d.ts
type AnymatchFn = (testString: string) => boolean;
type AnymatchPattern = string | RegExp | AnymatchFn;
type AnymatchMatcher = AnymatchPattern | AnymatchPattern[];
//#endregion
//#region src/types/chokidar.d.ts
declare class FSWatcher extends EventEmitter implements fs.FSWatcher {
options: WatchOptions;
/**
* Constructs a new FSWatcher instance with optional WatchOptions parameter.
*/
constructor(options?: WatchOptions);
/**
* When called, requests that the Node.js event loop not exit so long as the fs.FSWatcher is active.
* Calling watcher.ref() multiple times will have no effect.
*/
ref(): this;
/**
* When called, the active fs.FSWatcher object will not require the Node.js event loop to remain active.
* If there is no other activity keeping the event loop running, the process may exit before the fs.FSWatcher object's callback is invoked.
* Calling watcher.unref() multiple times will have no effect.
*/
unref(): this;
/**
* Add files, directories, or glob patterns for tracking. Takes an array of strings or just one
* string.
*/
add(paths: string | ReadonlyArray<string>): this;
/**
* Stop watching files, directories, or glob patterns. Takes an array of strings or just one
* string.
*/
unwatch(paths: string | ReadonlyArray<string>): this;
/**
* Returns an object representing all the paths on the file system being watched by this
* `FSWatcher` instance. The object's keys are all the directories (using absolute paths unless
* the `cwd` option was used), and the values are arrays of the names of the items contained in
* each directory.
*/
getWatched(): {
[directory: string]: string[];
};
/**
* Removes all listeners from watched files.
*/
close(): Promise<void>;
on(event: 'add' | 'addDir' | 'change', listener: (path: string, stats?: fs.Stats) => void): this;
on(event: 'all', listener: (eventName: 'add' | 'addDir' | 'change' | 'unlink' | 'unlinkDir', path: string, stats?: fs.Stats) => void): this;
/**
* Error occurred
*/
on(event: 'error', listener: (error: Error) => void): this;
/**
* Exposes the native Node `fs.FSWatcher events`
*/
on(event: 'raw', listener: (eventName: string, path: string, details: any) => void): this;
/**
* Fires when the initial scan is complete
*/
on(event: 'ready', listener: () => void): this;
on(event: 'unlink' | 'unlinkDir', listener: (path: string) => void): this;
on(event: string, listener: (...args: any[]) => void): this;
}
interface WatchOptions {
/**
* Indicates whether the process should continue to run as long as files are being watched. If
* set to `false` when using `fsevents` to watch, no more events will be emitted after `ready`,
* even if the process continues to run.
*/
persistent?: boolean;
/**
* ([anymatch](https://github.com/micromatch/anymatch)-compatible definition) Defines files/paths to
* be ignored. The whole relative or absolute path is tested, not just filename. If a function
* with two arguments is provided, it gets called twice per path - once with a single argument
* (the path), second time with two arguments (the path and the
* [`fs.Stats`](https://nodejs.org/api/fs.html#fs_class_fs_stats) object of that path).
*/
ignored?: AnymatchMatcher;
/**
* If set to `false` then `add`/`addDir` events are also emitted for matching paths while
* instantiating the watching as chokidar discovers these file paths (before the `ready` event).
*/
ignoreInitial?: boolean;
/**
* When `false`, only the symlinks themselves will be watched for changes instead of following
* the link references and bubbling events through the link's path.
*/
followSymlinks?: boolean;
/**
* The base directory from which watch `paths` are to be derived. Paths emitted with events will
* be relative to this.
*/
cwd?: string;
/**
* If set to true then the strings passed to .watch() and .add() are treated as literal path
* names, even if they look like globs.
*
* @default false
*/
disableGlobbing?: boolean;
/**
* Whether to use fs.watchFile (backed by polling), or fs.watch. If polling leads to high CPU
* utilization, consider setting this to `false`. It is typically necessary to **set this to
* `true` to successfully watch files over a network**, and it may be necessary to successfully
* watch files in other non-standard situations. Setting to `true` explicitly on OS X overrides
* the `useFsEvents` default.
*/
usePolling?: boolean;
/**
* Whether to use the `fsevents` watching interface if available. When set to `true` explicitly
* and `fsevents` is available this supersedes the `usePolling` setting. When set to `false` on
* OS X, `usePolling: true` becomes the default.
*/
useFsEvents?: boolean;
/**
* If relying upon the [`fs.Stats`](https://nodejs.org/api/fs.html#fs_class_fs_stats) object that
* may get passed with `add`, `addDir`, and `change` events, set this to `true` to ensure it is
* provided even in cases where it wasn't already available from the underlying watch events.
*/
alwaysStat?: boolean;
/**
* If set, limits how many levels of subdirectories will be traversed.
*/
depth?: number;
/**
* Interval of file system polling.
*/
interval?: number;
/**
* Interval of file system polling for binary files. ([see list of binary extensions](https://gi
* thub.com/sindresorhus/binary-extensions/blob/master/binary-extensions.json))
*/
binaryInterval?: number;
/**
* Indicates whether to watch files that don't have read permissions if possible. If watching
* fails due to `EPERM` or `EACCES` with this set to `true`, the errors will be suppressed
* silently.
*/
ignorePermissionErrors?: boolean;
/**
* `true` if `useFsEvents` and `usePolling` are `false`. Automatically filters out artifacts
* that occur when using editors that use "atomic writes" instead of writing directly to the
* source file. If a file is re-added within 100 ms of being deleted, Chokidar emits a `change`
* event rather than `unlink` then `add`. If the default of 100 ms does not work well for you,
* you can override it by setting `atomic` to a custom value, in milliseconds.
*/
atomic?: boolean | number;
/**
* can be set to an object in order to adjust timing params:
*/
awaitWriteFinish?: AwaitWriteFinishOptions | boolean;
}
interface AwaitWriteFinishOptions {
/**
* Amount of time in milliseconds for a file size to remain constant before emitting its event.
*/
stabilityThreshold?: number;
/**
* File size polling interval.
*/
pollInterval?: number;
}
/**
* produces an instance of `FSWatcher`.
*/
//#endregion
//#region src/types/connect.d.ts
declare namespace Connect {
export type ServerHandle = HandleFunction | http.Server;
export class IncomingMessage extends http.IncomingMessage {
originalUrl?: http.IncomingMessage['url'] | undefined;
}
export type NextFunction = (err?: any) => void;
export type SimpleHandleFunction = (req: IncomingMessage, res: http.ServerResponse) => void;
export type NextHandleFunction = (req: IncomingMessage, res: http.ServerResponse, next: NextFunction) => void;
export type ErrorHandleFunction = (err: any, req: IncomingMessage, res: http.ServerResponse, next: NextFunction) => void;
export type HandleFunction = SimpleHandleFunction | NextHandleFunction | ErrorHandleFunction;
export interface ServerStackItem {
route: string;
handle: ServerHandle;
}
export interface Server extends NodeJS.EventEmitter {
(req: http.IncomingMessage, res: http.ServerResponse, next?: Function): void;
route: string;
stack: ServerStackItem[];
/**
* Utilize the given middleware `handle` to the given `route`,
* defaulting to _/_. This "route" is the mount-point for the
* middleware, when given a value other than _/_ the middleware
* is only effective when that segment is present in the request's
* pathname.
*
* For example if we were to mount a function at _/admin_, it would
* be invoked on _/admin_, and _/admin/settings_, however it would
* not be invoked for _/_, or _/posts_.
*/
use(fn: NextHandleFunction): Server;
use(fn: HandleFunction): Server;
use(route: string, fn: NextHandleFunction): Server;
use(route: string, fn: HandleFunction): Server;
/**
* Handle server requests, punting them down
* the middleware stack.
*/
handle(req: http.IncomingMessage, res: http.ServerResponse, next: Function): void;
/**
* Listen for connections.
*
* This method takes the same arguments
* as node's `http.Server#listen()`.
*
* HTTP and HTTPS:
*
* If you run your application both as HTTP
* and HTTPS you may wrap them individually,
* since your Connect "server" is really just
* a JavaScript `Function`.
*
* var connect = require('connect')
* , http = require('http')
* , https = require('https');
*
* var app = connect();
*
* http.createServer(app).listen(80);
* https.createServer(options, app).listen(443);
*/
listen(port: number, hostname?: string, backlog?: number, callback?: Function): http.Server;
listen(port: number, hostname?: string, callback?: Function): http.Server;
listen(path: string, callback?: Function): http.Server;
listen(handle: any, listeningListener?: Function): http.Server;
}
}
//#endregion
//#region src/types/http-proxy.d.ts
declare namespace HttpProxy {
export type ProxyTarget = ProxyTargetUrl | ProxyTargetDetailed;
export type ProxyTargetUrl = string | Partial<url.Url>;
export interface ProxyTargetDetailed {
host: string;
port: number;
protocol?: string | undefined;
hostname?: string | undefined;
socketPath?: string | undefined;
key?: string | undefined;
passphrase?: string | undefined;
pfx?: Buffer | string | undefined;
cert?: string | undefined;
ca?: string | undefined;
ciphers?: string | undefined;
secureProtocol?: string | undefined;
}
export type ErrorCallback = (err: Error, req: http.IncomingMessage, res: http.ServerResponse, target?: ProxyTargetUrl) => void;
export class Server extends events.EventEmitter {
/**
* Creates the proxy server with specified options.
* @param options - Config object passed to the proxy
*/
constructor(options?: ServerOptions);
/**
* Used for proxying regular HTTP(S) requests
* @param req - Client request.
* @param res - Client response.
* @param options - Additional options.
* @param callback - Error callback.
*/
web(req: http.IncomingMessage, res: http.ServerResponse, options?: ServerOptions, callback?: ErrorCallback): void;
/**
* Used for proxying regular HTTP(S) requests
* @param req - Client request.
* @param socket - Client socket.
* @param head - Client head.
* @param options - Additional options.
* @param callback - Error callback.
*/
ws(req: http.IncomingMessage, socket: unknown, head: unknown, options?: ServerOptions, callback?: ErrorCallback): void;
/**
* A function that wraps the object in a webserver, for your convenience
* @param port - Port to listen on
*/
listen(port: number): Server;
/**
* A function that closes the inner webserver and stops listening on given port
*/
close(callback?: () => void): void;
/**
* Creates the proxy server with specified options.
* @param options - Config object passed to the proxy
* @returns Proxy object with handlers for `ws` and `web` requests
*/
static createProxyServer(options?: ServerOptions): Server;
/**
* Creates the proxy server with specified options.
* @param options - Config object passed to the proxy
* @returns Proxy object with handlers for `ws` and `web` requests
*/
static createServer(options?: ServerOptions): Server;
/**
* Creates the proxy server with specified options.
* @param options - Config object passed to the proxy
* @returns Proxy object with handlers for `ws` and `web` requests
*/
static createProxy(options?: ServerOptions): Server;
addListener(event: string, listener: () => void): this;
on(event: string, listener: () => void): this;
on(event: 'error', listener: ErrorCallback): this;
on(event: 'start', listener: (req: http.IncomingMessage, res: http.ServerResponse, target: ProxyTargetUrl) => void): this;
on(event: 'proxyReq', listener: (proxyReq: http.ClientRequest, req: http.IncomingMessage, res: http.ServerResponse, options: ServerOptions) => void): this;
on(event: 'proxyRes', listener: (proxyRes: http.IncomingMessage, req: http.IncomingMessage, res: http.ServerResponse) => void): this;
on(event: 'proxyReqWs', listener: (proxyReq: http.ClientRequest, req: http.IncomingMessage, socket: net.Socket, options: ServerOptions, head: any) => void): this;
on(event: 'econnreset', listener: (err: Error, req: http.IncomingMessage, res: http.ServerResponse, target: ProxyTargetUrl) => void): this;
on(event: 'end', listener: (req: http.IncomingMessage, res: http.ServerResponse, proxyRes: http.IncomingMessage) => void): this;
on(event: 'close', listener: (proxyRes: http.IncomingMessage, proxySocket: net.Socket, proxyHead: any) => void): this;
once(event: string, listener: () => void): this;
removeListener(event: string, listener: () => void): this;
removeAllListeners(event?: string): this;
getMaxListeners(): number;
setMaxListeners(n: number): this;
listeners(event: string): Array<() => void>;
emit(event: string, ...args: any[]): boolean;
listenerCount(type: string): number;
}
export interface ServerOptions {
/** URL string to be parsed with the url module. */
target?: ProxyTarget | undefined;
/** URL string to be parsed with the url module. */
forward?: ProxyTargetUrl | undefined;
/** Object to be passed to http(s).request. */
agent?: any;
/** Object to be passed to https.createServer(). */
ssl?: any;
/** If you want to proxy websockets. */
ws?: boolean | undefined;
/** Adds x- forward headers. */
xfwd?: boolean | undefined;
/** Verify SSL certificate. */
secure?: boolean | undefined;
/** Explicitly specify if we are proxying to another proxy. */
toProxy?: boolean | undefined;
/** Specify whether you want to prepend the target's path to the proxy path. */
prependPath?: boolean | undefined;
/** Specify whether you want to ignore the proxy path of the incoming request. */
ignorePath?: boolean | undefined;
/** Local interface string to bind for outgoing connections. */
localAddress?: string | undefined;
/** Changes the origin of the host header to the target URL. */
changeOrigin?: boolean | undefined;
/** specify whether you want to keep letter case of response header key */
preserveHeaderKeyCase?: boolean | undefined;
/** Basic authentication i.e. 'user:password' to compute an Authorization header. */
auth?: string | undefined;
/** Rewrites the location hostname on (301 / 302 / 307 / 308) redirects, Default: null. */
hostRewrite?: string | undefined;
/** Rewrites the location host/ port on (301 / 302 / 307 / 308) redirects based on requested host/ port.Default: false. */
autoRewrite?: boolean | undefined;
/** Rewrites the location protocol on (301 / 302 / 307 / 308) redirects to 'http' or 'https'.Default: null. */
protocolRewrite?: string | undefined;
/** rewrites domain of set-cookie headers. */
cookieDomainRewrite?: false | string | {
[oldDomain: string]: string;
} | undefined;
/** rewrites path of set-cookie headers. Default: false */
cookiePathRewrite?: false | string | {
[oldPath: string]: string;
} | undefined;
/** object with extra headers to be added to target requests. */
headers?: {
[header: string]: string;
} | undefined;
/** Timeout (in milliseconds) when proxy receives no response from target. Default: 120000 (2 minutes) */
proxyTimeout?: number | undefined;
/** Timeout (in milliseconds) for incoming requests */
timeout?: number | undefined;
/** Specify whether you want to follow redirects. Default: false */
followRedirects?: boolean | undefined;
/** If set to true, none of the webOutgoing passes are called and it's your responsibility to appropriately return the response by listening and acting on the proxyRes event */
selfHandleResponse?: boolean | undefined;
/** Buffer */
buffer?: stream.Stream | undefined;
}
}
//#endregion
//#region src/node/server/middlewares/proxy.d.ts
interface ProxyOptions extends HttpProxy.ServerOptions {
/**
* rewrite path
*/
rewrite?: (path: string) => string;
/**
* configure the proxy server (e.g. listen to events)
*/
configure?: (proxy: HttpProxy.Server, options: ProxyOptions) => void;
/**
* webpack-dev-server style bypass function
*/
bypass?: (req: http.IncomingMessage, /** undefined for WebSocket upgrade requests */
res: http.ServerResponse | undefined, options: ProxyOptions) => void | null | undefined | false | string | Promise<void | null | undefined | boolean | string>;
/**
* rewrite the Origin header of a WebSocket request to match the target
*
* **Exercise caution as rewriting the Origin can leave the proxying open to [CSRF attacks](https://owasp.org/www-community/attacks/csrf).**
*/
rewriteWsOrigin?: boolean | undefined;
}
//#endregion
//#region src/node/logger.d.ts
type LogType = 'error' | 'warn' | 'info';
type LogLevel = LogType | 'silent';
interface Logger {
info(msg: string, options?: LogOptions): void;
warn(msg: string, options?: LogOptions): void;
warnOnce(msg: string, options?: LogOptions): void;
error(msg: string, options?: LogErrorOptions): void;
clearScreen(type: LogType): void;
hasErrorLogged(error: Error | RollupError): boolean;
hasWarned: boolean;
}
interface LogOptions {
clear?: boolean;
timestamp?: boolean;
environment?: string;
}
interface LogErrorOptions extends LogOptions {
error?: Error | RollupError | null;
}
interface LoggerOptions {
prefix?: string;
allowClearScreen?: boolean;
customLogger?: Logger;
console?: Console;
}
declare function createLogger(level?: LogLevel, options?: LoggerOptions): Logger;
//#endregion
//#region src/node/http.d.ts
interface CommonServerOptions {
/**
* Specify server port. Note if the port is already being used, Vite will
* automatically try the next available port so this may not be the actual
* port the server ends up listening on.
*/
port?: number;
/**
* If enabled, vite will exit if specified port is already in use
*/
strictPort?: boolean;
/**
* Specify which IP addresses the server should listen on.
* Set to 0.0.0.0 to listen on all addresses, including LAN and public addresses.
*/
host?: string | boolean;
/**
* The hostnames that Vite is allowed to respond to.
* `localhost` and subdomains under `.localhost` and all IP addresses are allowed by default.
* When using HTTPS, this check is skipped.
*
* If a string starts with `.`, it will allow that hostname without the `.` and all subdomains under the hostname.
* For example, `.example.com` will allow `example.com`, `foo.example.com`, and `foo.bar.example.com`.
*
* If set to `true`, the server is allowed to respond to requests for any hosts.
* This is not recommended as it will be vulnerable to DNS rebinding attacks.
*/
allowedHosts?: string[] | true;
/**
* Enable TLS + HTTP/2.
* Note: this downgrades to TLS only when the proxy option is also used.
*/
https?: HttpsServerOptions;
/**
* Open browser window on startup
*/
open?: boolean | string;
/**
* Configure custom proxy rules for the dev server. Expects an object
* of `{ key: options }` pairs.
* Uses [`http-proxy`](https://github.com/http-party/node-http-proxy).
* Full options [here](https://github.com/http-party/node-http-proxy#options).
*
* Example `vite.config.js`:
* ``` js
* module.exports = {
* proxy: {
* // string shorthand: /foo -> http://localhost:4567/foo
* '/foo': 'http://localhost:4567',
* // with options
* '/api': {
* target: 'http://jsonplaceholder.typicode.com',
* changeOrigin: true,
* rewrite: path => path.replace(/^\/api/, '')
* }
* }
* }
* ```
*/
proxy?: Record<string, string | ProxyOptions>;
/**
* Configure CORS for the dev server.
* Uses https://github.com/expressjs/cors.
*
* When enabling this option, **we recommend setting a specific value
* rather than `true`** to avoid exposing the source code to untrusted origins.
*
* Set to `true` to allow all methods from any origin, or configure separately
* using an object.
*
* @default false
*/
cors?: CorsOptions | boolean;
/**
* Specify server response headers.
*/
headers?: OutgoingHttpHeaders;
}
/**
* https://github.com/expressjs/cors#configuration-options
*/
interface CorsOptions {
/**
* Configures the Access-Control-Allow-Origin CORS header.
*
* **We recommend setting a specific value rather than
* `true`** to avoid exposing the source code to untrusted origins.
*/
origin?: CorsOrigin | ((origin: string | undefined, cb: (err: Error, origins: CorsOrigin) => void) => void);
methods?: string | string[];
allowedHeaders?: string | string[];
exposedHeaders?: string | string[];
credentials?: boolean;
maxAge?: number;
preflightContinue?: boolean;
optionsSuccessStatus?: number;
}
type CorsOrigin = boolean | string | RegExp | (string | RegExp)[];
//#endregion
//#region src/node/typeUtils.d.ts
type RequiredExceptFor<T, K extends keyof T> = Pick<T, K> & Required<Omit<T, K>>;
//#endregion
//#region src/node/preview.d.ts
interface PreviewOptions extends CommonServerOptions {}
interface ResolvedPreviewOptions extends RequiredExceptFor<PreviewOptions, 'host' | 'https' | 'proxy'> {}
interface PreviewServer {
/**
* The resolved vite config object
*/
config: ResolvedConfig;
/**
* Stop the server.
*/
close(): Promise<void>;
/**
* 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: HttpServer;
/**
* The resolved urls Vite prints on the CLI (URL-encoded). Returns `null`
* if the server is not listening on any port.
*/
resolvedUrls: ResolvedServerUrls | null;
/**
* Print server urls
*/
printUrls(): void;
/**
* Bind CLI shortcuts
*/
bindCLIShortcuts(options?: BindCLIShortcutsOptions<PreviewServer>): void;
}
type PreviewServerHook = (this: MinimalPluginContextWithoutEnvironment, server: PreviewServer) => (() => void) | void | Promise<(() => void) | void>;
/**
* Starts the Vite server in preview mode, to simulate a production deployment
*/
declare function preview(inlineConfig?: InlineConfig): Promise<PreviewServer>;
//#endregion
//#region src/node/shortcuts.d.ts
type BindCLIShortcutsOptions<Server = ViteDevServer | PreviewServer> = {
/**
* Print a one-line shortcuts "help" hint to the terminal
*/
print?: boolean;
/**
* Custom shortcuts to run when a key is pressed. These shortcuts take priority
* over the default shortcuts if they have the same keys (except the `h` key).
* To disable a default shortcut, define the same key but with `action: undefined`.
*/
customShortcuts?: CLIShortcut<Server>[];
};
type CLIShortcut<Server = ViteDevServer | PreviewServer> = {
key: string;
description: string;
action?(server: Server): void | Promise<void>;
};
//#endregion
//#region src/node/baseEnvironment.d.ts
declare class PartialEnvironment {
name: string;
getTopLevelConfig(): ResolvedConfig;
config: ResolvedConfig & ResolvedEnvironmentOptions;
logger: Logger;
constructor(name: string, topLevelConfig: ResolvedConfig, options?: ResolvedEnvironmentOptions);
}
declare class BaseEnvironment extends PartialEnvironment {
get plugins(): readonly Plugin$1[];
constructor(name: string, config: ResolvedConfig, options?: ResolvedEnvironmentOptions);
}
/**
* This class discourages users from inversely checking the `mode`
* to determine the type of environment, e.g.
*
* ```js
* const isDev = environment.mode !== 'build' // bad
* const isDev = environment.mode === 'dev' // good
* ```
*
* You should also not check against `"unknown"` specifically. It's
* a placeholder for more possible environment types.
*/
declare class UnknownEnvironment extends BaseEnvironment {
mode: "unknown";
}
//#endregion
//#region src/node/optimizer/scan.d.ts
declare class ScanEnvironment extends BaseEnvironment {
mode: "scan";
get pluginContainer(): EnvironmentPluginContainer;
init(): Promise<void>;
}
//#endregion
//#region src/node/optimizer/index.d.ts
type ExportsData = {
hasModuleSyntax: boolean;
exports: readonly string[];
jsxLoader?: boolean;
};
interface DepsOptimizer {
init: () => Promise<void>;
metadata: DepOptimizationMetadata;
scanProcessing?: Promise<void>;
registerMissingImport: (id: string, resolved: string) => OptimizedDepInfo;
run: () => void;
isOptimizedDepFile: (id: string) => boolean;
isOptimizedDepUrl: (url: string) => boolean;
getOptimizedDepId: (depInfo: OptimizedDepInfo) => string;
close: () => Promise<void>;
options: DepOptimizationOptions;
}
interface DepOptimizationConfig {
/**
* Force optimize listed dependencies (must be resolvable import paths,
* cannot be globs).
*/
include?: string[];
/**
* Do not optimize these dependencies (must be resolvable import paths,
* cannot be globs).
*/
exclude?: string[];
/**
* Forces ESM interop when importing these dependencies. Some legacy
* packages advertise themselves as ESM but use `require` internally
* @experimental
*/
needsInterop?: string[];
/**
* Options to pass to esbuild during the dep scanning and optimization
*
* Certain options are omitted since changing them would not be compatible
* with Vite's dep optimization.
*
* - `external` is also omitted, use Vite's `optimizeDeps.exclude` option
* - `plugins` are merged with Vite's dep plugin
*
* https://esbuild.github.io/api
*/
esbuildOptions?: Omit<esbuild_BuildOptions, 'bundle' | 'entryPoints' | 'external' | 'write' | 'watch' | 'outdir' | 'outfile' | 'outbase' | 'outExtension' | 'metafile'>;
/**
* List of file extensions that can be optimized. A corresponding esbuild
* plugin must exist to handle the specific extension.
*
* By default, Vite can optimize `.mjs`, `.js`, `.ts`, and `.mts` files. This option
* allows specifying additional extensions.
*
* @experimental
*/
extensions?: string[];
/**
* Deps optimization during build was removed in Vite 5.1. This option is
* now redundant and will be removed in a future version. Switch to using
* `optimizeDeps.noDiscovery` and an empty or undefined `optimizeDeps.include`.
* true or 'dev' disables the optimizer, false or 'build' leaves it enabled.
* @default 'build'
* @deprecated
* @experimental
*/
disabled?: boolean | 'build' | 'dev';
/**
* Automatic dependency discovery. When `noDiscovery` is true, only dependencies
* listed in `include` will be optimized. The scanner isn't run for cold start
* in this case. CJS-only dependencies must be present in `include` during dev.
* @default false
*/
noDiscovery?: boolean;
/**
* When enabled, it will hold the first optimized deps results until all static
* imports are crawled on cold start. This avoids the need for full-page reloads
* when new dependencies are discovered and they trigger the generation of new
* common chunks. If all dependencies are found by the scanner plus the explicitly
* defined ones in `include`, it is better to disable this option to let the
* browser process more requests in parallel.
* @default true
* @experimental
*/
holdUntilCrawlEnd?: boolean;
}
type DepOptimizationOptions = DepOptimizationConfig & {
/**
* By default, Vite will crawl your `index.html` to detect dependencies that
* need to be pre-bundled. If `build.rollupOptions.input` is specified, Vite
* will crawl those entry points instead.
*
* If neither of these fit your needs, you can specify custom entries using
* this option - the value should be a tinyglobby pattern or array of patterns
* (https://github.com/SuperchupuDev/tinyglobby) that are relative from
* vite project root. This will overwrite default entries inference.
*/
entries?: string | string[];
/**
* Force dep pre-optimization regardless of whether deps have changed.
* @experimental
*/
force?: boolean;
};
interface OptimizedDepInfo {
id: string;
file: string;
src?: string;
needsInterop?: boolean;
browserHash?: string;
fileHash?: string;
/**
* During optimization, ids can still be resolved to their final location
* but the bundles may not yet be saved to disk
*/
processing?: Promise<void>;
/**
* ExportData cache, discovered deps will parse the src entry to get exports
* data used both to define if interop is needed and when pre-bundling
*/
exportsData?: Promise<ExportsData>;
}
interface DepOptimizationMetadata {
/**
* The main hash is determined by user config and dependency lockfiles.
* This is checked on server startup to avoid unnecessary re-bundles.
*/
hash: string;
/**
* This hash is determined by dependency lockfiles.
* This is checked on server startup to avoid unnecessary re-bundles.
*/
lockfileHash: string;
/**
* This hash is determined by user config.
* This is checked on server startup to avoid unnecessary re-bundles.
*/
configHash: string;
/**
* The browser hash is determined by the main hash plus additional dependencies
* discovered at runtime. This is used to invalidate browser requests to
* optimized deps.
*/
browserHash: string;
/**
* Metadata for each already optimized dependency
*/
optimized: Record<string, OptimizedDepInfo>;
/**
* Metadata for non-entry optimized chunks and dynamic imports
*/
chunks: Record<string, OptimizedDepInfo>;
/**
* Metadata for each newly discovered dependency after processing
*/
discovered: Record<string, OptimizedDepInfo>;
/**
* OptimizedDepInfo list
*/
depInfoList: OptimizedDepInfo[];
}
/**
* Scan and optimize dependencies within a project.
* Used by Vite CLI when running `vite optimize`.
*
* @deprecated the optimization process runs automatically and does not need to be called
*/
declare function optimizeDeps(config: ResolvedConfig, force?: boolean | undefined, asCommand?: boolean): Promise<DepOptimizationMetadata>;
//#endregion
//#region src/node/server/transformRequest.d.ts
interface TransformResult {
code: string;
map: SourceMap | {
mappings: '';
} | null;
ssr?: boolean;
etag?: string;
deps?: string[];
dynamicDeps?: string[];
}
interface TransformOptions {
/**
* @deprecated inferred from environment
*/
ssr?: boolean;
}
//#endregion
//#region src/node/server/moduleGraph.d.ts
declare class EnvironmentModuleNode {
environment: string;
/**
* Public served url path, starts with /
*/
url: string;
/**
* Resolved file system path + query
*/
id: string | null;
file: string | null;
type: 'js' | 'css';
info?: ModuleInfo;
meta?: Record<string, any>;
importers: Set<EnvironmentModuleNode>;
importedModules: Set<EnvironmentModuleNode>;
acceptedHmrDeps: Set<EnvironmentModuleNode>;
acceptedHmrExports: Set<string> | null;
importedBindings: Map<string, Set<string>> | null;
isSelfAccepting?: boolean;
transformResult: TransformResult | null;
ssrModule: Record<string, any> | null;
ssrError: Error | null;
lastHMRTimestamp: number;
lastInvalidationTimestamp: number;
/**
* @param setIsSelfAccepting - set `false` to set `isSelfAccepting` later. e.g. #7870
*/
constructor(url: string, environment: string, setIsSelfAccepting?: boolean);
}
type ResolvedUrl = [url: string, resolvedId: string, meta: object | null | undefined];
declare class EnvironmentModuleGraph {
environment: string;
urlToModuleMap: Map<string, EnvironmentModuleNode>;
idToModuleMap: Map<string, EnvironmentModuleNode>;
etagToModuleMap: Map<string, EnvironmentModuleNode>;
fileToModulesMap: Map<string, Set<EnvironmentModuleNode>>;
constructor(environment: string, resolveId: (url: string) => Promise<PartialResolvedId | null>);
getModuleByUrl(rawUrl: string): Promise<EnvironmentModuleNode | undefined>;
getModuleById(id: string): EnvironmentModuleNode | undefined;
getModulesByFile(file: string): Set<EnvironmentModuleNode> | undefined;
onFileChange(file: string): void;
onFileDelete(file: string): void;
invalidateModule(mod: EnvironmentModuleNode, seen?: Set<EnvironmentModuleNode>, timestamp?: number, isHmr?: boolean, ): void;
invalidateAll(): void;
/**
* Update the module graph based on a module's updated imports information
* If there are dependencies that no longer have any importers, they are
* returned as a Set.
*
* @param staticImportedUrls Subset of `importedModules` where they're statically imported in code.
* This is only used for soft invalidations so `undefined` is fine but may cause more runtime processing.
*/
updateModuleInfo(mod: EnvironmentModuleNode, importedModules: Set<string | EnvironmentModuleNode>, importedBindings: Map<string, Set<string>> | null, acceptedModules: Set<string | EnvironmentModuleNode>, acceptedExports: Set<string> | null, isSelfAccepting: boolean, ): Promise<Set<EnvironmentModuleNode> | undefined>;
ensureEntryFromUrl(rawUrl: string, setIsSelfAccepting?: boolean): Promise<EnvironmentModuleNode>;
createFileOnlyEntry(file: string): EnvironmentModuleNode;
resolveUrl(url: string): Promise<ResolvedUrl>;
updateModuleTransformResult(mod: EnvironmentModuleNode, result: TransformResult | null): void;
getModuleByEtag(etag: string): EnvironmentModuleNode | undefined;
}
//#endregion
//#region src/node/server/mixedModuleGraph.d.ts
declare class ModuleNode {
_moduleGraph: ModuleGraph;
_clientModule: EnvironmentModuleNode | undefined;
_ssrModule: EnvironmentModuleNode | undefined;
constructor(moduleGraph: ModuleGraph, clientModule?: EnvironmentModuleNode, ssrModule?: EnvironmentModuleNode);
_get<T extends keyof EnvironmentModuleNode>(prop: T): EnvironmentModuleNode[T];
_set<T extends keyof EnvironmentModuleNode>(prop: T, value: EnvironmentModuleNode[T]): void;
_wrapModuleSet(prop: ModuleSetNames, module: EnvironmentModuleNode | undefined): Set<ModuleNode>;
_getModuleSetUnion(prop: 'importedModules' | 'importers'): Set<ModuleNode>;
_getModuleInfoUnion(prop: 'info'): ModuleInfo | undefined;
_getModuleObjectUnion(prop: 'meta'): Record<string, any> | undefined;
get url(): string;
set url(value: string);
get id(): string | null;
set id(value: string | null);
get file(): string | null;
set file(value: string | null);
get type(): 'js' | 'css';
get info(): ModuleInfo | undefined;
get meta(): Record<string, any> | undefined;
get importers(): Set<ModuleNode>;
get clientImportedModules(): Set<ModuleNode>;
get ssrImportedModules(): Set<ModuleNode>;
get importedModules(): Set<ModuleNode>;
get acceptedHmrDeps(): Set<ModuleNode>;
get acceptedHmrExports(): Set<string> | null;
get importedBindings(): Map<string, Set<string>> | null;
get isSelfAccepting(): boolean | undefined;
get transformResult(): TransformResult | null;
set transformResult(value: TransformResult | null);
get ssrTransformResult(): TransformResult | null;
set ssrTransformResult(value: TransformResult | null);
get ssrModule(): Record<string, any> | null;
get ssrError(): Error | null;
get lastHMRTimestamp(): number;
set lastHMRTimestamp(value: number);
get lastInvalidationTimestamp(): number;
get invalidationState(): TransformResult | 'HARD_INVALIDATED' | undefined;
get ssrInvalidationState(): TransformResult | 'HARD_INVALIDATED' | undefined;
}
declare class ModuleGraph {
urlToModuleMap: Map<string, ModuleNode>;
idToModuleMap: Map<string, ModuleNode>;
etagToModuleMap: Map<string, ModuleNode>;
fileToModulesMap: Map<string, Set<ModuleNode>>;
private moduleNodeCache;
constructor(moduleGraphs: {
client: () => EnvironmentModuleGraph;
ssr: () => EnvironmentModuleGraph;
});
getModuleById(id: string): ModuleNode | undefined;
getModuleByUrl(url: string, _ssr?: boolean): Promise<ModuleNode | undefined>;
getModulesByFile(file: string): Set<ModuleNode> | undefined;
onFileChange(file: string): void;
onFileDelete(file: string): void;
invalidateModule(mod: ModuleNode, seen?: Set<ModuleNode>, timestamp?: number, isHmr?: boolean, ): void;
invalidateAll(): void;
ensureEntryFromUrl(rawUrl: string, ssr?: boolean, setIsSelfAccepting?: boolean): Promise<ModuleNode>;
createFileOnlyEntry(file: string): ModuleNode;
resolveUrl(url: string, ssr?: boolean): Promise<ResolvedUrl>;
updateModuleTransformResult(mod: ModuleNode, result: TransformResult | null, ssr?: boolean): void;
getModuleByEtag(etag: string): ModuleNode | undefined;
getBackwardCompatibleBrowserModuleNode(clientModule: EnvironmentModuleNode): ModuleNode;
getBackwardCompatibleServerModuleNode(ssrModule: EnvironmentModuleNode): ModuleNode;
getBackwardCompatibleModuleNode(mod: EnvironmentModuleNode): ModuleNode;
getBackwardCompatibleModuleNodeDual(clientModule?: EnvironmentModuleNode, ssrModule?: EnvironmentModuleNode): ModuleNode;
}
type ModuleSetNames = 'acceptedHmrDeps' | 'importedModules';
//#endregion
//#region src/node/server/hmr.d.ts
interface HmrOptions {
protocol?: string;
host?: string;
port?: number;
clientPort?: number;
path?: string;
timeout?: number;
overlay?: boolean;
server?: HttpServer;
}
interface HotUpdateOptions {
type: 'create' | 'update' | 'delete';
file: string;
timestamp: number;
modules: Array<EnvironmentModuleNode>;
read: () => string | Promise<string>;
server: ViteDevServer;
}
interface HmrContext {
file: string;
timestamp: number;
modules: Array<ModuleNode>;
read: () => string | Promise<string>;
server: ViteDevServer;
}
interface HotChannelClient {
send(payload: hmrPayload_HotPayload): void;
}
type HotChannelListener<T extends string = string> = (data: InferCustomEventPayload<T>, client: HotChannelClient) => void;
interface HotChannel<Api = any> {
/**
* Broadcast events to all clients
*/
send?(payload: hmrPayload_HotPayload): void;
/**
* Handle custom event emitted by `import.meta.hot.send`
*/
on?<T extends string>(event: T, listener: HotChannelListener<T>): void;
on?(event: 'connection', listener: () => void): void;
/**
* Unregister event listener
*/
off?(event: string, listener: Function): void;
/**
* Start listening for messages
*/
listen?(): void;
/**
* Disconnect all clients, called when server is closed or restarted.
*/
close?(): Promise<unknown> | void;
api?: Api;
}
interface NormalizedHotChannelClient {
/**
* Send event to the client
*/
send(payload: hmrPayload_HotPayload): void;
/**
* Send custom event
*/
send(event: string, payload?: hmrPayload_CustomPayload['data']): void;
}
interface NormalizedHotChannel<Api = any> {
/**
* Broadcast events to all clients
*/
send(payload: hmrPayload_HotPayload): void;
/**
* Send custom event
*/
send<T extends string>(event: T, payload?: InferCustomEventPayload<T>): void;
/**
* Handle custom event emitted by `import.meta.hot.send`
*/
on<T extends string>(event: T, listener: (data: InferCustomEventPayload<T>, client: NormalizedHotChannelClient) => void): void;
on(event: 'connection', listener: () => void): void;
/**
* Unregister event listener
*/
off(event: string, listener: Function): void;
handleInvoke(payload: hmrPayload_HotPayload): Promise<{
result: any;
} | {
error: any;
}>;
/**
* Start listening for messages
*/
listen(): void;
/**
* Disconnect all clients, called when server is closed or restarted.
*/
close(): Promise<unknown> | void;
api?: Api;
}
type ServerHotChannelApi = {
innerEmitter: EventEmitter;
outsideEmitter: EventEmitter;
};
type ServerHotChannel = HotChannel<ServerHotChannelApi>;
type NormalizedServerHotChannel = NormalizedHotChannel<ServerHotChannelApi>;
declare function createServerHotChannel(): ServerHotChannel;
//#endregion
//#region src/types/ws.d.ts
// WebSocket socket.
declare class WebSocket extends EventEmitter {
/** The connection is not yet open. */
static readonly CONNECTING: 0;
/** The connection is open and ready to communicate. */
static readonly OPEN: 1;
/** The connection is in the process of closing. */
static readonly CLOSING: 2;
/** The connection is closed. */
static readonly CLOSED: 3;
binaryType: 'nodebuffer' | 'arraybuffer' | 'fragments';
readonly bufferedAmount: number;
readonly extensions: string;
/** Indicates whether the websocket is paused */
readonly isPaused: boolean;
readonly protocol: string;
/** The current state of the connection */
readonly readyState: typeof WebSocket.CONNECTING | typeof WebSocket.OPEN | typeof WebSocket.CLOSING | typeof WebSocket.CLOSED;
readonly url: string;
/** The connection is not yet open. */
readonly CONNECTING: 0;
/** The connection is open and ready to communicate. */
readonly OPEN: 1;
/** The connection is in the process of closing. */
readonly CLOSING: 2;
/** The connection is closed. */
readonly CLOSED: 3;
onopen: ((event: WebSocket.Event) => void) | null;
onerror: ((event: WebSocket.ErrorEvent) => void) | null;
onclose: ((event: WebSocket.CloseEvent) => void) | null;
onmessage: ((event: WebSocket.MessageEvent) => void) | null;
constructor(address: null);
constructor(address: string | URL, options?: WebSocket.ClientOptions | ClientRequestArgs);
constructor(address: string | URL, protocols?: string | string[], options?: WebSocket.ClientOptions | ClientRequestArgs);
close(code?: number, data?: string | Buffer): void;
ping(data?: any, mask?: boolean, cb?: (err: Error) => void): void;
pong(data?: any, mask?: boolean, cb?: (err: Error) => void): void;
send(data: any, cb?: (err?: Error) => void): void;
send(data: any, options: {
mask?: boolean | undefined;
binary?: boolean | undefined;
compress?: boolean | undefined;
fin?: boolean | undefined;
}, cb?: (err?: Error) => void): void;
terminate(): void;
/**
* Pause the websocket causing it to stop emitting events. Some events can still be
* emitted after this is called, until all buffered data is consumed. This method
* is a noop if the ready state is `CONNECTING` or `CLOSED`.
*/
pause(): void;
/**
* Make a paused socket resume emitting events. This method is a noop if the ready
* state is `CONNECTING` or `CLOSED`.
*/
resume(): void;
// HTML5 WebSocket events
addEventListener(method: 'message', cb: (event: WebSocket.MessageEvent) => void, options?: WebSocket.EventListenerOptions): void;
addEventListener(method: 'close', cb: (event: WebSocket.CloseEvent) => void, options?: WebSocket.EventListenerOptions): void;
addEventListener(method: 'error', cb: (event: WebSocket.ErrorEvent) => void, options?: WebSocket.EventListenerOptions): void;
addEventListener(method: 'open', cb: (event: WebSocket.Event) => void, options?: WebSocket.EventListenerOptions): void;
removeEventListener(method: 'message', cb: (event: WebSocket.MessageEvent) => void): void;
removeEventListener(method: 'close', cb: (event: WebSocket.CloseEvent) => void): void;
removeEventListener(method: 'error', cb: (event: WebSocket.ErrorEvent) => void): void;
removeEventListener(method: 'open', cb: (event: WebSocket.Event) => void): void;
// Events
on(event: 'close', listener: (this: WebSocket, code: number, reason: Buffer) => void): this;
on(event: 'error', listener: (this: WebSocket, err: Error) => void): this;
on(event: 'upgrade', listener: (this: WebSocket, request: http.IncomingMessage) => void): this;
on(event: 'message', listener: (this: WebSocket, data: WebSocket.RawData, isBinary: boolean) => void): this;
on(event: 'open', listener: (this: WebSocket) => void): this;
on(event: 'ping' | 'pong', listener: (this: WebSocket, data: Buffer) => void): this;
on(event: 'unexpected-response', listener: (this: WebSocket, request: ClientRequest, response: http.IncomingMessage) => void): this;
on(event: string | symbol, listener: (this: WebSocket, ...args: any[]) => void): this;
once(event: 'close', listener: (this: WebSocket, code: number, reason: Buffer) => void): this;
once(event: 'error', listener: (this: WebSocket, err: Error) => void): this;
once(event: 'upgrade', listener: (this: WebSocket, request: http.IncomingMessage) => void): this;
once(event: 'message', listener: (this: WebSocket, data: WebSocket.RawData, isBinary: boolean) => void): this;
once(event: 'open', listener: (this: WebSocket) => void): this;
once(event: 'ping' | 'pong', listener: (this: WebSocket, data: Buffer) => void): this;
once(event: 'unexpected-response', listener: (this: WebSocket, request: ClientRequest, response: http.IncomingMessage) => void): this;
once(event: string | symbol, listener: (this: WebSocket, ...args: any[]) => void): this;
off(e