This hook is used to monitor file changes and page updates in your ProcessWire project. It operates when debug mode is active and returns file changes and latest page update information in JSON format.
The script hook is automatically injected before the </body> tag in your HTML. It periodically checks for any file or page updates in your system at the interval you specify. If the previous check time is older than the new check time (indicating changes), the page automatically refreshes.
~/site/ready.php
if ($wire->config->debug) {
$wire->addHookAfter('Page::render', function (HookEvent $event) {
$script = <<<HTML
<script>
const browserSync = {
mtime: 0,
init() {
this.sync();
},
sync() {
fetch('/browser-sync')
.then(response => response.json())
.then(data => {
if (!this.mtime) {
this.mtime = data.max;
} else {
if (data.max > this.mtime) {
location.reload();
}
}
});
}
};
browserSync.init();
setInterval(() => browserSync.sync(), 2500);
</script>
HTML;
$event->return = str_replace('</body>', "{$script}</body>", $event->return);
});
$wire->addHook('/browser-sync', function (HookEvent $event) {
$wire = $event->wire();
$root = $wire->config->paths->root;
$siteRoot = $wire->config->paths->site;
$extensions = '*.{php,js,css}';
$paths = [
"{$root}src/{$extensions}", // custom composer package
"{$root}src/src/{$extensions}", // custom composer package
"{$siteRoot}{$extensions}", // ready.php, init.php, finished.php
"{$siteRoot}classes/{$extensions}", // page classes
"{$siteRoot}templates/{$extensions}",
"{$siteRoot}templates/*/{$extensions}",
"{$siteRoot}templates/*/*/{$extensions}",
"{$siteRoot}templates/*/*/*/{$extensions}",
"{$siteRoot}templates/*/*/*/*/{$extensions}",
];
$files = [];
foreach ($paths as $pattern) {
// Try with GLOB_BRACE first
$result = glob($pattern, GLOB_NOSORT | GLOB_BRACE);
// If no results with GLOB_BRACE, try without it
if (!$result) {
$result = glob($pattern, GLOB_NOSORT) ?: [];
}
$files = array_merge($files, $result);
}
$filemtime = 0;
foreach ($files as $file) {
if (!is_file($file)) {
continue;
}
try {
$mtime = @filemtime($file);
if ($mtime && $mtime > $filemtime) {
$filemtime = $mtime;
}
} catch (\Exception $e) {
continue;
}
}
$latest = $wire->pages->get('sort=-created|-modified');
$latestTime = $latest->modified > $latest->created ? $latest->modified : $latest->created;
header('Content-Type: application/javascript');
echo json_encode([
'max' => max($filemtime, $latestTime),
'mtime' => $filemtime,
'modified' => $latest->modified,
'created' => $latest->created
]);
exit;
});
}
This development tool helps streamline your workflow by automatically refreshing the browser when you make changes to your files or content, eliminating the need for manual page refreshes during development.