Don't let third-party script failures mask a working app
The boot guard reported every failed resource behind a full-screen #boot-error panel. Cloudflare injects beacon.min.js at the edge, and ad blockers and filtering DNS block it routinely, so a blocked analytics script painted "CourseHub failed to start" over an app that had started fine. Mark the resources we actually ship with data-boot-critical and ignore the rest, and stop showing the panel once app.js has a UI on screen — that also keeps a late unhandled rejection (a dropped fetch in loadMeta, a flaky scan) from covering a running app. A genuine failure of app.js itself still reports as before. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TD5SRevPpgFguCwzNv9ZR7
This commit is contained in:
@@ -26,16 +26,23 @@ function asset(string $path): string
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
|
||||
<link href="https://cdn.jsdelivr.net/npm/plyr@3.7.8/dist/plyr.css" rel="stylesheet">
|
||||
<link href="<?= asset('assets/style.css') ?>" rel="stylesheet">
|
||||
<link href="https://cdn.jsdelivr.net/npm/plyr@3.7.8/dist/plyr.css" rel="stylesheet" data-boot-critical>
|
||||
<link href="<?= asset('assets/style.css') ?>" rel="stylesheet" data-boot-critical>
|
||||
|
||||
<!-- Installed before every other script so it can report failures in them
|
||||
(including assets/app.js itself). Without it a JS error leaves the shell
|
||||
hidden and the page simply blank, with the reason only in the console. -->
|
||||
hidden and the page simply blank, with the reason only in the console.
|
||||
|
||||
The report is a full-screen panel, so it is deliberately hard to trigger:
|
||||
only resources carrying data-boot-critical count, and only until app.js
|
||||
signals that it has put a UI on screen. Anything else — Cloudflare's
|
||||
injected analytics beacon, a blocked font, a failing fetch long after
|
||||
boot — goes to the console instead of over a working app. -->
|
||||
<script>
|
||||
(function () {
|
||||
var box = null;
|
||||
function report(kind, detail) {
|
||||
if (window.__chBooted) { console.error('CourseHub — ' + kind + ':', detail); return; }
|
||||
if (!box) {
|
||||
box = document.createElement('pre');
|
||||
box.id = 'boot-error';
|
||||
@@ -48,6 +55,10 @@ function asset(string $path): string
|
||||
window.addEventListener('error', function (e) {
|
||||
var el = e.target;
|
||||
if (el && el !== window && (el.src || el.href)) {
|
||||
if (!(el.hasAttribute && el.hasAttribute('data-boot-critical'))) {
|
||||
console.warn('CourseHub — non-critical resource failed:', el.src || el.href);
|
||||
return;
|
||||
}
|
||||
report('Failed to load', el.src || el.href);
|
||||
} else {
|
||||
report('Error', (e.message || e.error) +
|
||||
@@ -126,8 +137,8 @@ function asset(string $path): string
|
||||
<div class="toasts" id="toasts"></div>
|
||||
<div id="overlay-root"></div>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/plyr@3.7.8/dist/plyr.min.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/animejs@3.2.2/lib/anime.min.js"></script>
|
||||
<script src="<?= asset('assets/app.js') ?>"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/plyr@3.7.8/dist/plyr.min.js" data-boot-critical></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/animejs@3.2.2/lib/anime.min.js" data-boot-critical></script>
|
||||
<script src="<?= asset('assets/app.js') ?>" data-boot-critical></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
Reference in New Issue
Block a user