Inspect the intermediate state of Vite plugins during development and build processes
—
RPC functions for programmatic access to inspection data from external tools and automated workflows.
Access to the plugin's RPC interface for programmatic inspection.
interface ViteInspectAPI {
/** RPC functions for accessing inspection data */
rpc: RpcFunctions;
}The plugin instance exposes an api property after being configured in a Vite server:
// Access the API from a configured plugin
const inspect = Inspect({ dev: true });
// In configureServer hook or after server setup
const api: ViteInspectAPI = inspect.api;
const data = await api.rpc.getMetadata();Complete interface for all available RPC functions.
interface RpcFunctions {
/** Get metadata about all Vite instances and their configurations */
getMetadata(): Promise<Metadata>;
/** Get list of all modules for a specific environment */
getModulesList(query: QueryEnv): Promise<ModulesList>;
/** Get detailed transformation info for a specific module */
getModuleTransformInfo(query: QueryEnv, id: string, clear?: boolean): Promise<ModuleTransformInfo>;
/** Get performance metrics for all plugins */
getPluginMetrics(query: QueryEnv): Promise<PluginMetricInfo[]>;
/** Get server middleware performance metrics */
getServerMetrics(query: QueryEnv): Promise<ServerMetrics>;
/** Resolve a module ID using Vite's resolution logic */
resolveId(query: QueryEnv, id: string): Promise<string>;
/** Notify when modules have been updated (for UI synchronization) */
onModuleUpdated(): Promise<void>;
}Environment and instance identification for RPC calls.
interface QueryEnv {
/** Vite instance ID */
vite: string;
/** Environment name ('client', 'ssr', etc.) */
env: string;
}
interface QueryId extends QueryEnv {
/** Module ID to query */
id: string;
}Usage Example:
// Query for client environment of a specific Vite instance
const query: QueryEnv = {
vite: 'vite-instance-id',
env: 'client'
};
const modules = await rpc.getModulesList(query);
const metrics = await rpc.getPluginMetrics(query);Get comprehensive metadata about Vite instances and their configurations.
interface Metadata {
/** Array of all Vite instance information */
instances: InstanceInfo[];
/** Whether embedded mode is enabled */
embedded?: boolean;
}
interface InstanceInfo {
/** Project root directory */
root: string;
/** Unique Vite instance identifier */
vite: string;
/** Array of environment names */
environments: string[];
/** Serialized plugin information */
plugins: SerializedPlugin[];
/** Mapping of environment names to plugin indices */
environmentPlugins: Record<string, number[]>;
}
interface SerializedPlugin {
/** Plugin name */
name: string;
/** Plugin enforcement mode */
enforce?: string;
/** Serialized resolveId hook */
resolveId: string;
/** Serialized load hook */
load: string;
/** Serialized transform hook */
transform: string;
/** Serialized generateBundle hook */
generateBundle: string;
/** Serialized handleHotUpdate hook */
handleHotUpdate: string;
/** Serialized api property */
api: string;
}Usage Example:
const metadata = await rpc.getMetadata();
console.log(`Found ${metadata.instances.length} Vite instances`);
metadata.instances.forEach(instance => {
console.log(`Instance: ${instance.vite}`);
console.log(`Root: ${instance.root}`);
console.log(`Environments: ${instance.environments.join(', ')}`);
console.log(`Plugins: ${instance.plugins.length}`);
});Programmatically resolve module IDs using Vite's resolution logic.
/**
* Resolve a module ID using Vite's resolution logic
* @param query - Environment query parameters
* @param id - Module ID to resolve
* @returns Promise resolving to the resolved module path
*/
resolveId(query: QueryEnv, id: string): Promise<string>;Usage Example:
// Resolve a relative import
const resolvedPath = await rpc.resolveId(
{ vite: 'instance-id', env: 'client' },
'./components/Button'
);
console.log('Resolved to:', resolvedPath);
// Resolve an npm package
const packagePath = await rpc.resolveId(
{ vite: 'instance-id', env: 'client' },
'vue'
);
console.log('Vue resolved to:', packagePath);Control caching behavior for module transformation info.
// Get cached transformation info
const transformInfo = await rpc.getModuleTransformInfo(
{ vite: 'instance-id', env: 'client' },
'/src/App.vue',
false // don't clear cache
);
// Get fresh transformation info (clear cache)
const freshTransformInfo = await rpc.getModuleTransformInfo(
{ vite: 'instance-id', env: 'client' },
'/src/App.vue',
true // clear cache first
);Subscribe to module update notifications for real-time monitoring.
// Set up update monitoring
const monitorUpdates = async () => {
try {
await rpc.onModuleUpdated();
console.log('Modules have been updated');
// Refresh data after updates
const updatedModules = await rpc.getModulesList({ vite: 'instance-id', env: 'client' });
console.log(`Now tracking ${updatedModules.length} modules`);
// Continue monitoring
monitorUpdates();
} catch (error) {
console.error('Update monitoring failed:', error);
// Retry after delay
setTimeout(monitorUpdates, 1000);
}
};
monitorUpdates();class PerformanceMonitor {
constructor(private rpc: RpcFunctions, private query: QueryEnv) {}
async generateReport() {
const [modules, metrics, serverMetrics] = await Promise.all([
this.rpc.getModulesList(this.query),
this.rpc.getPluginMetrics(this.query),
this.rpc.getServerMetrics(this.query)
]);
return {
timestamp: new Date().toISOString(),
moduleCount: modules.length,
slowestModules: modules
.sort((a, b) => b.totalTime - a.totalTime)
.slice(0, 10)
.map(m => ({ id: m.id, time: m.totalTime })),
pluginMetrics: metrics
.sort((a, b) => (b.transform.totalTime + b.resolveId.totalTime) - (a.transform.totalTime + a.resolveId.totalTime))
.slice(0, 5)
.map(p => ({
name: p.name,
totalTime: p.transform.totalTime + p.resolveId.totalTime,
calls: p.transform.invokeCount + p.resolveId.invokeCount
})),
serverMetrics
};
}
async watchPerformance(callback: (report: any) => void) {
const monitor = async () => {
try {
const report = await this.generateReport();
callback(report);
// Wait for next update
await this.rpc.onModuleUpdated();
setTimeout(monitor, 1000); // Debounce updates
} catch (error) {
console.error('Performance monitoring error:', error);
setTimeout(monitor, 5000); // Retry after error
}
};
monitor();
}
}
// Usage
const monitor = new PerformanceMonitor(rpc, { vite: 'instance-id', env: 'client' });
monitor.watchPerformance(report => {
console.log('Performance Report:', report);
// Alert on performance issues
if (report.slowestModules[0]?.time > 1000) {
console.warn(`Slow module detected: ${report.slowestModules[0].id} (${report.slowestModules[0].time}ms)`);
}
});async function analyzeBuild(rpc: RpcFunctions, query: QueryEnv) {
const metadata = await rpc.getMetadata();
const modules = await rpc.getModulesList(query);
const metrics = await rpc.getPluginMetrics(query);
const analysis = {
overview: {
totalModules: modules.length,
virtualModules: modules.filter(m => m.virtual).length,
totalSourceSize: modules.reduce((sum, m) => sum + m.sourceSize, 0),
totalDistSize: modules.reduce((sum, m) => sum + m.distSize, 0)
},
performance: {
totalPluginTime: metrics.reduce((sum, p) => sum + p.transform.totalTime + p.resolveId.totalTime, 0),
slowestPlugins: metrics
.sort((a, b) => (b.transform.totalTime + b.resolveId.totalTime) - (a.transform.totalTime + a.resolveId.totalTime))
.slice(0, 5),
modulesBySize: modules
.sort((a, b) => b.distSize - a.distSize)
.slice(0, 10)
},
dependencies: {
highlyImported: modules
.sort((a, b) => b.importers.length - a.importers.length)
.slice(0, 10)
.map(m => ({ id: m.id, importerCount: m.importers.length })),
heavyDependencies: modules
.sort((a, b) => b.deps.length - a.deps.length)
.slice(0, 10)
.map(m => ({ id: m.id, depCount: m.deps.length }))
}
};
return analysis;
}Install with Tessl CLI
npx tessl i tessl/npm-vite-plugin-inspect