diff --git a/vite-plugin-laravel/src/blade.ts b/vite-plugin-laravel/src/blade.ts deleted file mode 100644 index 9d52b0f..0000000 --- a/vite-plugin-laravel/src/blade.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { Plugin } from 'vite' - -/** - * Fully reload the page when a blade file is updated. - */ -export const blade = (): Plugin => ({ - name: 'laravel:blade-reload', - handleHotUpdate({ file, server }) { - if (['.blade.php', 'vite.php'].some((name) => file.endsWith(name))) { - server.ws.send({ - type: 'full-reload', - path: '*', - }) - } - }, -}) - -// server.watcher.add(watchAdditionalPaths) diff --git a/vite-plugin-laravel/src/index.ts b/vite-plugin-laravel/src/index.ts index f5ed45a..6853d8d 100644 --- a/vite-plugin-laravel/src/index.ts +++ b/vite-plugin-laravel/src/index.ts @@ -1,7 +1,8 @@ import { PluginOption, UserConfig } from 'vite' import { manifest } from './manifest' import { config } from './config' -import { blade } from './blade' +import { reload } from './reload' +import { callArtisan, callShell, findPhpPath } from './utils' import type { Options } from './types' export function defineConfig(base: UserConfig = {}) { @@ -10,18 +11,18 @@ export function defineConfig(base: UserConfig = {}) { plugins: [ ...base?.plugins as any, config(), - blade(), + reload(), manifest(), ], } } export const laravel = (options: Options = {}): PluginOption[] => [ - blade(), + reload(options), config(options), manifest(), ] -export { manifest, blade, config } +export { manifest, reload, config, callArtisan, callShell, findPhpPath } export default laravel diff --git a/vite-plugin-laravel/src/reload.ts b/vite-plugin-laravel/src/reload.ts new file mode 100644 index 0000000..37e1f85 --- /dev/null +++ b/vite-plugin-laravel/src/reload.ts @@ -0,0 +1,62 @@ +import { Plugin, ViteDevServer } from 'vite' +import makeDebugger from 'debug' +import { Options, WatchOptions } from './types' + +const PREFIX = 'vite:laravel:reload' +const debug = makeDebugger(PREFIX) + +/** + * Reload when some files are changed. + */ +export const reload = (options: Options = {}): Plugin => { + const watchOptions: Required = { + input: [], + reloadOnBladeUpdates: true, + reloadOnConfigUpdates: true, + ...(Array.isArray(options.watch) ? { input: options.watch } : options.watch), + } + + debug('Given options:', options) + debug('Resolved options:', watchOptions) + + // When the config change, we want a full module graph + // invalidation as well as a full reload + watchOptions.input.push({ + condition: (file) => file.endsWith('config/vite.php'), + handle: ({ server }) => { + debug('Configuration file changed, invalidating module graph and reloading') + server.moduleGraph.invalidateAll() + server.ws.send({ type: 'full-reload', path: '*' }) + }, + }) + + // Blade files + watchOptions.input.push({ + condition: (file) => file.endsWith('.blade.php'), + handle: ({ server }) => { + debug('Blade file changed, reloading') + server.ws.send({ type: 'full-reload', path: '*' }) + }, + }) + + function handleReload(file: string, server: ViteDevServer) { + file = file.replaceAll('\\', '/') + + watchOptions.input.forEach((value) => { + if (value.condition(file)) { + debug(`${file} changed, applying its handler`) + value.handle({ file, server }) + } + }) + } + + return { + name: 'vite:laravel:reload', + configureServer(server) { + server.watcher + .on('add', (path) => handleReload(path, server)) + .on('change', (path) => handleReload(path, server)) + .on('unlink', (path) => handleReload(path, server)) + }, + } +} diff --git a/vite-plugin-laravel/src/types.ts b/vite-plugin-laravel/src/types.ts index 3f9010d..6f54341 100644 --- a/vite-plugin-laravel/src/types.ts +++ b/vite-plugin-laravel/src/types.ts @@ -1,4 +1,4 @@ -import type { SSROptions } from 'vite' +import type { SSROptions, ViteDevServer } from 'vite' export interface ServerConfiguration { default: keyof ServerConfiguration['configs'] @@ -69,6 +69,27 @@ export interface Options { * @default true */ allowOverrides?: boolean + + /** + * List of file changes to listen to. + */ + watch?: WatchInput[] | WatchOptions +} + +export interface WatchOptions { + reloadOnBladeUpdates?: boolean + reloadOnConfigUpdates?: boolean + input?: WatchInput[] +} + +export interface WatchInputHandlerParameters { + file: string + server: ViteDevServer +} + +export interface WatchInput { + condition: (file: string) => boolean + handle: (parameters: WatchInputHandlerParameters) => void } export interface Certificates {