White Screen Detection
Frontend white screen refers to when users open a webpage and the page fails to load or render properly, resulting in a blank display in the browser. This is usually caused by JavaScript errors, resource loading failures, network issues, or rendering logic errors. Particularly in Single Page Applications (SPAs), frontend white screen issues become more complex and may prevent users from seeing any valid content. Resolving white screen issues requires quickly locating and fixing errors to ensure proper resource loading and rendering.
White Screen Manifestations and Causes
White screens typically manifest in the following ways:
-
Blank Page: When users open the page, they only see a blank browser window with no content displayed. The page hasn’t rendered at all, and the background is usually white.
-
Loading State Stuck: During page loading, there might be a loading animation or progress bar, but it remains stagnant with no progress for an extended period, eventually becoming blank.
-
Partial Elements Missing: Sometimes certain page content fails to render, with only some elements (like backgrounds or certain frameworks) showing while other parts completely disappear, resulting in an incomplete page.
-
Browser Error Messages: In development environments, developers might see browser console error messages (like JavaScript errors or resource loading failures), while users only see a blank page.
-
No Response to Interactions: The page is blank and unresponsive to any interaction. Users’ attempts to click or scroll the page yield no response.
-
Completely Empty or Black Screen: Instead of a completely white screen, the page has no content, and the background might turn black or gray, usually indicating abnormal page rendering.
White screens are caused by two types of issues: resource loading errors and code execution errors.
Resource Loading Errors
Resource loading errors typically refer to when static files or network requests that the page depends on fail to load successfully, preventing the page from displaying content. Common resource loading errors include:
-
JavaScript File Loading Failure: If essential JavaScript files fail to load (possibly due to incorrect file paths, network issues, server failures, etc.), dynamic functionality on the page cannot execute, leading to blank screens.
-
CSS File Loading Failure: If page stylesheets fail to load, page element layout and styles cannot be applied, potentially causing the page to appear blank.
-
Static Resource Loading Failure: If static resources like images and fonts that the page depends on fail to load, it may result in incomplete page content or even blank screens.
-
API Request Failure: If the page needs to fetch data through APIs and the API requests fail or return errors (like 404 or 500 errors), dynamic content on the page may fail to render.
Code Execution Errors
Code execution errors refer to issues that occur when JavaScript scripts run in the browser, interrupting the page rendering process. Common code execution errors include:
-
JavaScript Runtime Errors: During script execution on the page, uncaught exceptions might occur (such as accessing undefined variables or calling non-existent functions), which prevent subsequent code execution and prevent page rendering.
-
Framework Rendering Errors: When using frontend frameworks like React, Vue, or Angular, if framework component rendering encounters errors (such as component data anomalies or state management errors), it may result in blank screens.
-
Asynchronous Code Issues: Frontend code heavily relies on asynchronous operations (like using fetch or axios for API requests). If these asynchronous operations fail (due to network issues, server errors, etc.), page rendering may fail.
-
Infinite Loops or Deadlocks: Logic errors in frontend code (like infinite recursion or endless loops) can cause the JavaScript engine to crash or hang, preventing page rendering.
Detection Method Comparison
Method | Principle | Advantages | Disadvantages |
---|---|---|---|
Root Node Mount Detection | Monitors whether DOM is mounted under a root node in SPA frameworks by listening to onload and onerror events | Low development cost | Poor compatibility, only works with mainstream SPA frameworks |
DOM Change Monitoring | Uses Mutation Observer API to monitor DOM changes | Relatively low development cost | Low accuracy, cannot detect unrendered content. May lose state after rendering completes, may fail if user doesn’t interact with DOM for long periods |
Page Screenshot Comparison | Takes screenshots and compares them with previous versions | Technically simple, good applicability | Low accuracy, cannot detect background images and loading page backgrounds |
Frontend Error & Memory Overflow Detection | Uses ErrorBoundary component to catch JS exceptions and detect page anomalies | Relatively low development cost | Cannot detect abnormal screens, only framework-level issues |
Page Element Key-Value Comparison | Examines interactions/cross-validates styles using elementsFromPoint API to get element information | High accuracy, low technical difficulty | Higher development cost |
elementsFromPoint is a JavaScript API that gets all DOM elements at specified screen coordinates. Through this method, you can obtain all elements at given coordinates in stacking order (top to bottom).
Example usage:
document.elementsFromPoint(x, y);
The main differences between these frontend white screen detection methods lie in their detection principles and applicable scenarios:
-
Root Node Mount Detection mainly determines if page loading is successful by monitoring root node events. Suitable for simple SPA frameworks but has poor compatibility.
-
DOM Change Monitoring uses the
MutationObserver
API to dynamically monitor DOM changes. Suitable for dynamic rendering but has low accuracy and cannot detect unrendered content. -
Page Screenshot Comparison determines if the page is rendered correctly by comparing current screenshots with expected ones. Suitable for checking page completeness but cannot handle dynamic content.
-
Frontend Error Detection detects page crashes by capturing JavaScript errors. Suitable for framework error detection but cannot capture display anomalies.
-
Page Element Comparison uses the
elementsFromPoint
API to get page element information and check display status. High accuracy but higher development cost, suitable for complex pages.
Each method differs in accuracy, development difficulty, and applicable scope.
Based on the above comparison, using ‘Page Key Point Sampling Comparison’ proves to be a better implementation approach.
Note that for scenarios with iframes embedded in the main application, since each sampling only captures the entire iframe element, it’s impossible to determine if the iframe is showing a white screen from the main application. The white screen detection SDK needs to be integrated within the iframe application itself.
Data Collection
This flowchart details the steps of frontend white screen detection, particularly considering the special case of skeleton screen applications. First, the system determines if the page is a skeleton screen application. This is because skeleton screens are placeholders during page loading, typically showing a simple framework or animation to indicate that the page is loading. The skeleton screen itself might display a white screen state, so additional judgment is needed to ensure false positives are avoided.
If the page is a skeleton screen application, the system then checks if the page has finished loading or if there are loading errors. If the page loads successfully without errors, the system performs screen sampling during browser idle time to determine if the current page meets white screen criteria. If the criteria are met, indicating a possible white screen state, the system further checks if polling detection is enabled. If not enabled, the system will start polling detection; if already enabled, the system compares initial sampling results with subsequent results to ensure the page hasn’t changed. If the results differ, indicating a possible white screen, the system will report the error.
The entire process ensures accurate identification and reporting of white screen issues through these judgment steps, particularly in special cases like skeleton screens, avoiding false positives.
Screen Sampling Point Selection
There are three methods for selecting sampling points: vertical sampling, cross sampling, and vertical cross sampling.
Vertical Sampling
Vertical sampling refers to sampling page content from top to bottom along the vertical direction, either line by line or at certain intervals. This method can effectively detect page rendering, particularly suitable for pages with obvious vertical layouts (such as articles, blogs, etc.).
However, if the page has horizontal layouts or large amounts of dynamically loaded content, vertical sampling might not fully cover the page’s rendering state.
Cross Sampling
Cross sampling involves sampling from multiple locations on the page simultaneously, covering both vertical and horizontal directions. Typically, it detects by alternately selecting sampling points from different page areas. Cross sampling can capture more page details, particularly suitable for multi-column layouts or complex page structures (such as news websites, e-commerce platforms, etc.), providing a more comprehensive view of page rendering. Compared to vertical sampling, cross sampling requires more computational resources and has more sampling points, making implementation more complex and potentially causing additional performance overhead.
Vertical Cross Sampling
Vertical cross sampling combines features of both vertical and cross sampling, sampling both vertically from top to bottom and alternating horizontal sampling between different vertical lines. This covers a broader page area, checking both overall layout and details, suitable for complex page structures. Due to increased sampling points, the computational load is higher, potentially impacting performance, so practical applications need to balance detection accuracy with performance overhead.
To overcome the performance issues of vertical cross sampling, we can use requestIdleCallback to perform calculations during browser idle time. Since requestIdleCallback only runs during idle periods, it won’t block page rendering or affect user operation response time, effectively reducing computational burden.
White Screen Detection Criteria and Timing
Detection methods and timing differ slightly between applications with and without skeleton screens.
Scenarios Without Skeleton Screens
Determining the timing for detecting visible elements is a key challenge - improper timing can lead to misjudgments. If detection occurs too early, temporary blanks during page loading might be mistaken for white screens, failing to accurately reflect the page’s final rendering state. If detection occurs too late, white screen incidents might be missed when users close pages due to long wait times. Therefore, choosing appropriate detection timing is crucial to avoid both premature judgment and delayed reporting.
Detection Timing
Detection timing consists of several aspects:
-
After Page Load: When the page has loaded completely without any loading errors, monitoring begins initial sampling. The startMonitoring method, serving as the monitoring entry point, calls requestIdleCallback to perform sampling during browser idle time.
-
Browser Idle Time Sampling: Using requestIdleCallback to execute sampling tasks ensures sampling operations don’t block page rendering and user interaction. requestIdleCallback ensures execution during browser idle time, improving performance and reducing impact on user experience.
-
Page Content Change Detection: During each sampling, the system compares current sampling data with initial sampling data to check for page changes. If changes occur, the system reports anomalies (reportAnomaly method) and initiates retry mechanisms (retrySampling method).
-
White Screen Detection: The system checks for blank areas during each sampling. If blank areas exceed the set threshold, the page is considered white screen and triggers reporting. White screen detection is based on the presence and visibility of page elements, using multiple sampling points to enhance accuracy.
-
Retry Mechanism: When page changes or white screens are detected, the system initiates a retry mechanism. Through the retrySampling method, the system performs multiple samplings based on maximum retry counts and intervals until detecting page changes or reaching maximum retries.
-
Stop Monitoring: During monitoring, if special circumstances occur (e.g., page request cancellation or forced page stop), the stopMonitoring method can be called to stop monitoring. When called, requestIdleCallback stops sampling and monitoring tasks are cleared to avoid unnecessary resource consumption.
Detection Methods
Detection methods for applications without skeleton screens include several aspects:
-
Root Container Initialization and Configuration: When initializing the SDK, we need to configure root containers based on page structure. If the root container is empty (no valid container elements in the page), it’s considered a white screen. In the code, root container element determination is implemented through the isContainer method, which determines valid root containers by checking if element tagNames are common container elements (like DIV, SECTION, MAIN, HEADER, FOOTER).
-
Sampling Point Calculation and Detection: By obtaining page width (window.innerWidth) and height (window.innerHeight), the code calculates multiple sampling point coordinates covering various directions (including X-axis, Y-axis, ascending diagonal, and descending diagonal). Using document.elementsFromPoint method to get DOM elements at each coordinate and determining if these elements are valid root container elements. Empty point count increases when sampling points lack valid container elements.
-
White Screen Detection: After each sampling, the system checks for blank areas on the page. When blank areas exceed the set threshold, the page is considered white screen and reported. To avoid missing micro-frontend or iframe scenario sub-applications, the code designates the lower right area as the content area, checking sampling points in this area to determine white screen conditions. This ensures white screen issues in sub-applications can be detected even if the main application shows no white screen.
-
Retry Mechanism: When detecting page content changes or white screens, the system initiates a retry mechanism. Through the retrySampling method, the system performs multiple samplings within set maximum retry counts and intervals until page state changes or maximum retries are reached. This mechanism ensures monitoring can capture state changes even during dynamic page changes.
-
Stop Monitoring: When special circumstances occur (like request cancellation or forced page stop), monitoring stops. Through the stopMonitoring method, requestIdleCallback stops sampling tasks and clears timers to avoid unnecessary resource consumption.
As shown above, the entire screen has 33 sampling points, with 28 in the content area. For simplicity, when detecting white screens, we determine if blank sampling points are greater than or equal to 28. Sampling point coordinates are obtained as follows:
for (let i = 1; i <= 9; i++) {
// x-axis sampling points
const xElements = document?.elementsFromPoint(
(window.innerWidth * i) / 10,
window.innerHeight / 2,
);
// y-axis sampling points
const yElements = document?.elementsFromPoint(
window.innerWidth / 2,
(window.innerHeight * i) / 10,
);
// ascending diagonal sampling points
const upDiagonalElements = document?.elementsFromPoint(
(window.innerWidth * i) / 10,
(window.innerHeight * i) / 10,
);
// descending diagonal sampling points
const downDiagonalElements = document?.elementsFromPoint(
(window.innerWidth * i) / 10,
window.innerHeight - (window.innerHeight * i) / 10,
);
// Get sample data for each direction
sampleData[`xElement_${i}`] = this.getElementSample(xElements[0]);
sampleData[`yElement_${i}`] = this.getElementSample(yElements[0]);
sampleData[`upDiagonalElement_${i}`] = this.getElementSample(upDiagonalElements[0]);
sampleData[`downDiagonalElement_${i}`] = this.getElementSample(downDiagonalElements[0]);
// Check if it's an empty point (no valid content or invisible) and check if it's a container
if (!this.isElementVisible(xElements[0]) || !this.isContainer(xElements[0] as HTMLElement)) {
this.emptyPoints++;
}
if (i !== 5) {
// Avoid duplicate calculation of center point
if (!this.isElementVisible(yElements[0]) || !this.isContainer(yElements[0] as HTMLElement)) {
this.emptyPoints++;
}
if (
!this.isElementVisible(upDiagonalElements[0]) ||
!this.isContainer(upDiagonalElements[0] as HTMLElement)
) {
this.emptyPoints++;
}
if (
!this.isElementVisible(downDiagonalElements[0]) ||
!this.isContainer(downDiagonalElements[0] as HTMLElement)
) {
this.emptyPoints++;
}
}
}
Skeleton Screen Scenarios
Detection timing consists of several aspects:
-
Monitor Skeleton Screen Disappearance: Use MutationObserver to monitor DOM changes, triggering white screen detection when skeleton screen is removed from the page.
-
Timeout Mechanism: If skeleton screen doesn’t disappear within skeletonMaxWaitTime, force white screen detection to prevent infinite page waiting.
-
White Screen Detection After Skeleton Screen Disappearance: Once skeleton screen is removed, immediately check if page has valid content to ensure proper rendering.
Detection Methods
If an application has a skeleton screen, continuing to use non-skeleton screen application’s white screen detection methods becomes ineffective because skeleton screens are valid DOM elements.
import { Logger } from './Logger';
import { SDKConfig } from './types';
export class SkeletonScreenMonitor {
private config: SDKConfig;
private onSkeletonDisappear: () => void;
private onWhiteScreenDetected: () => void; // Added: white screen callback
private logger: Logger;
private isSkeletonScreenGone: boolean = false; // Ensure callback is executed only once
private observer: MutationObserver | null = null; // Store MutationObserver instance
private timeoutId: number | null = null; // Store timer ID
constructor(
config: SDKConfig,
onSkeletonDisappear: () => void,
onWhiteScreenDetected: () => void,
logger: Logger,
) {
this.config = config;
this.onSkeletonDisappear = onSkeletonDisappear;
this.onWhiteScreenDetected = onWhiteScreenDetected; // Initialize white screen callback
this.logger = logger;
}
// Monitor skeleton screen disappearance and start white screen detection
waitForSkeletonToDisappear(): void {
const skeleton = document.querySelector(this.config.skeletonSelector);
if (!skeleton) {
this.logger.info('No skeleton screen detected');
this.triggerSkeletonDisappear(); // If no skeleton screen detected, directly call callback
return;
}
this.observer = new MutationObserver((mutations) => {
mutations.forEach((mutation) => {
mutation.removedNodes.forEach((removedNode) => {
if (removedNode instanceof Element && removedNode.matches(this.config.skeletonSelector)) {
this.logger.info('Skeleton screen disappeared');
this.disconnectObserver(); // Disconnect observer when skeleton screen disappears
this.triggerSkeletonDisappear(); // Call callback when skeleton screen disappears
this.checkForWhiteScreen(); // Check for white screen after skeleton screen disappears
}
});
});
});
this.observer.observe(document.body, { childList: true, subtree: true });
// Set timeout mechanism, if skeleton screen doesn't disappear within maximum wait time, force trigger callback
this.timeoutId = window.setTimeout(() => {
this.disconnectObserver();
if (!this.isSkeletonScreenGone) {
this.logger.warn('Skeleton screen wait timeout');
this.triggerSkeletonDisappear();
}
this.checkForWhiteScreen(); // Check for white screen after timeout
}, this.config.skeletonMaxWaitTime);
}
// Trigger callback for skeleton screen disappearance and ensure it's triggered only once
private triggerSkeletonDisappear(): void {
if (!this.isSkeletonScreenGone) {
this.isSkeletonScreenGone = true;
this.onSkeletonDisappear(); // Ensure callback is executed only once
}
}
// Check if the page has valid content and determine if it's a white screen
private checkForWhiteScreen(): void {
const visibleContent = this.getVisibleContent();
if (visibleContent === 0) {
this.logger.error('White screen detected');
this.onWhiteScreenDetected(); // Call white screen callback
} else {
this.logger.info(`Visible content detected: ${visibleContent} elements`);
}
}
// Get the number of visible elements on the page
private getVisibleContent(): number {
const visibleElements = document.querySelectorAll(this.config.contentSelector); // Get content of parent container
let visibleCount = 0;
// Iterate through all child elements under the parent container and check their display status
visibleElements.forEach((element) => {
// Check if the element is visible
const rect = element.getBoundingClientRect();
const computedStyle = window.getComputedStyle(element);
// Only count as visible when element has dimensions and is not hidden
if (
rect.width > 0 &&
rect.height > 0 &&
computedStyle.visibility !== 'hidden' &&
computedStyle.display !== 'none'
) {
visibleCount++;
}
});
return visibleCount;
}
// Disconnect observer and clear timer
disconnectObserver(): void {
if (this.observer) {
this.observer.disconnect();
this.logger.info('Disconnected skeleton screen observer');
this.observer = null;
}
if (this.timeoutId) {
clearTimeout(this.timeoutId);
this.logger.info('Cleared skeleton screen timeout');
this.timeoutId = null;
}
}
}
In the SkeletonScreenMonitor class, white screen detection primarily involves monitoring skeleton screen disappearance and determining appropriate timing to check if the page renders valid content. The skeleton screen serves as a placeholder during page loading, and when removed, it indicates that real page content should have loaded, triggering white screen detection at this time. The checkForWhiteScreen method is called after skeleton screen disappearance to check for visible content on the page. If no visible content exists, the onWhiteScreenDetected callback triggers, indicating a white screen.
The specific detection method is the getVisibleContent method, which iterates through page elements, checking if they have non-zero dimensions and if visibility isn’t hidden and display isn’t none, thus determining if the page has truly rendered content. If no visible elements meet these conditions, it’s considered a white screen and triggers corresponding callbacks.
Additionally, to prevent cases where skeleton screens don’t disappear for extended periods, the code includes a timeout mechanism. If the skeleton screen hasn’t been removed within the maximum wait time, onWhiteScreenDetected is forcibly triggered, ensuring white screen detection isn’t skipped due to skeleton screen persistence. To accurately capture skeleton screen disappearance, MutationObserver monitors document.body changes, executing white screen detection immediately upon skeleton screen removal to ensure normal page rendering. Even after skeleton screen removal, confirmation of main content loading is still necessary to prevent false judgments.
References
Summary
Front-end white screen refers to a scenario where users encounter a blank browser display when accessing a web page due to failed loading or rendering, typically caused by resource loading failures, code execution errors, or network issues. This problem is particularly complex in Single Page Applications (SPAs), potentially leaving users unable to view any meaningful content.
White screen detection can be implemented through various approaches. Common methods include monitoring root node events, using MutationObserver to track DOM changes, screenshot comparison, front-end error monitoring, and page element analysis. Each method varies in accuracy, development complexity, and applicability. Sampling point-based detection, for example, evaluates whether a page is blank by checking multiple sampling points for valid content, requiring a balance between performance overhead and detection precision. Typical sampling strategies include vertical sampling, cross sampling, and vertical-cross hybrid sampling.
To ensure detection accuracy, white screen detection tools typically combine page loading status, the timing of skeleton screen disappearance, and content rendering state to determine if a white screen occurs. Special attention is needed for sub-application detection in micro-frontend and iframe scenarios. By refining white screen detection, issues can be identified early, reducing the likelihood of critical failures and improving user experience.