11import { relative , resolve } from 'path'
22import colors from 'picocolors'
33import picomatch from 'picomatch'
4+ import debounce from 'debounce'
45import { type PluginOption , type ViteDevServer , normalizePath } from 'vite'
56
67/**
@@ -19,6 +20,15 @@ export interface Config {
1920 */
2021 delay ?: number
2122
23+ /**
24+ * How many milliseconds to postpone the execution of the reload function since it's last invocation.
25+ * This is useful if you have a lot of changes in a short period of time and need to make sure that
26+ * we only send one `full-reload` to Vite.
27+ *
28+ * @default 0
29+ */
30+ debounce ?: number
31+
2232 /**
2333 * Whether to log when a file change triggers a full reload.
2434 * @default true
@@ -48,13 +58,15 @@ export default (paths: string | string[], config: Config = {}): PluginOption =>
4858 config : ( ) => ( { server : { watch : { disableGlobbing : false } } } ) ,
4959
5060 configureServer ( { watcher, ws, config : { logger } } : ViteDevServer ) {
51- const { root = process . cwd ( ) , log = true , always = true , delay = 0 } = config
61+ const { root = process . cwd ( ) , log = true , always = true , delay = 0 , debounce : debounceMs = 0 } = config
5262
5363 const files = normalizePaths ( root , paths )
5464 const shouldReload = picomatch ( files )
65+ const sendReloadEvent = ( path : string ) => setTimeout ( ( ) => ws . send ( { type : 'full-reload' , path : always ? '*' : path } ) , delay )
66+ const reload = debounceMs ? debounce ( sendReloadEvent , debounceMs ) : sendReloadEvent
5567 const checkReload = ( path : string ) => {
5668 if ( shouldReload ( path ) ) {
57- setTimeout ( ( ) => ws . send ( { type : 'full- reload' , path : always ? '*' : path } ) , delay )
69+ reload ( path )
5870 if ( log )
5971 logger . info ( `${ colors . green ( 'page reload' ) } ${ colors . dim ( relative ( root , path ) ) } ` , { clear : true , timestamp : true } )
6072 }
0 commit comments