Skip to content

SAV/Backport: Fix home-page SSR->CSR flicker#1311

Open
jr-rk wants to merge 5 commits into
customer/savfrom
sav/fe-fix-home-page-flicker
Open

SAV/Backport: Fix home-page SSR->CSR flicker#1311
jr-rk wants to merge 5 commits into
customer/savfrom
sav/fe-fix-home-page-flicker

Conversation

@jr-rk

@jr-rk jr-rk commented Jun 17, 2026

Copy link
Copy Markdown

Problem description

Backport from #1287

Analysis

(Write here, if there is needed describe some specific problem. Erase it, when it is not needed.)

Problems

(Write here, if some unexpected problems occur during solving issues. Erase it, when it is not needed.)

Sync verification

If en.json5 or cs.json5 translation files were updated:

  • Run yarn run sync-i18n -t src/assets/i18n/cs.json5 -i to synchronize messages, and changes are included in this PR.

Manual Testing (if applicable)

Copilot review

  • Requested review from Copilot

Summary by CodeRabbit

  • New Features

    • Implemented anti-flicker overlay for server-side rendered content to provide smoother initial page load without visual flashing.
  • Bug Fixes

    • Resolved home-page flicker issue when using custom themes.
  • Chores

    • Updated production bundle size thresholds to accommodate application growth.
    • Enhanced test coverage for app initialization behavior.

@jr-rk jr-rk self-assigned this Jun 17, 2026
@coderabbitai

coderabbitai Bot commented Jun 17, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 89af4f0e-3923-4a34-a7be-dbc9eafd0977

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Backports an SSR→CSR anti-flicker mechanism for the home page by keeping the SSR-rendered DOM visible during Angular 15’s client bootstrap rebuild, then removing the mask once the app becomes stable.

Changes:

  • Add an inline “SSR overlay” script + CSS in index.html and a corresponding teardown hook in AppComponent using ApplicationRef.isStable.
  • Re-enable CustomEagerThemeModule to avoid lazy-loading themed wrappers that exacerbate visible gaps.
  • Add typings + unit tests for the new window.__dspaceRemoveSsrOverlay global and adjust bundle budgets.

Reviewed changes

Copilot reviewed 5 out of 9 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
src/typings.d.ts Declares the window.__dspaceRemoveSsrOverlay global for TS type safety.
src/themes/eager-themes.module.ts Imports CustomEagerThemeModule eagerly to reduce flicker caused by lazy wrapper loading.
src/index.html Adds SSR overlay CSS + inline bootstrap script to preserve SSR DOM/styles until CSR is stable.
src/app/app.component.ts Calls overlay teardown once ApplicationRef.isStable emits true (outside Angular zone).
src/app/app.component.spec.ts Adds unit tests validating overlay teardown behavior.
angular.json Raises initial bundle size budgets to accommodate eager theme inclusion.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/index.html Outdated
Comment thread src/app/app.component.spec.ts Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
src/app/app.component.spec.ts (1)

132-188: ⚡ Quick win

Add coverage for the no-requestAnimationFrame fallback branch.

The new tests only exercise the rAF-present path. Please add one case with window.requestAnimationFrame unset and assert the remover still runs after the 50ms delay, so both scheduler branches are protected.

Proposed test addition
   it('is a no-op when the global is not injected (e.g. CSR-only route, SSR skipped)', fakeAsync(() => {
@@
     expect(window.__dspaceRemoveSsrOverlay).toBeUndefined();
   }));
+
+  it('removes the overlay when requestAnimationFrame is unavailable', fakeAsync(() => {
+    const spy = jasmine.createSpy('__dspaceRemoveSsrOverlay');
+    window.__dspaceRemoveSsrOverlay = spy;
+    (window as any).requestAnimationFrame = undefined;
+
+    const f = TestBed.createComponent(AppComponent);
+    f.detectChanges();
+
+    isStable$.next(true);
+    tick(50);
+    flush();
+
+    expect(spy).toHaveBeenCalledTimes(1);
+  }));

As per coding guidelines, “New features must include new unit tests”.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/app/app.component.spec.ts` around lines 132 - 188, Add a new test case in
the removeSsrOverlayWhenStable describe block to cover the fallback path when
requestAnimationFrame is not available. In this test, delete
window.requestAnimationFrame (or set it to undefined) before constructing the
AppComponent, then verify that the __dspaceRemoveSsrOverlay spy is still called
exactly once after the 50ms delay using fakeAsync, tick, and flush. This ensures
the removeSsrOverlayWhenStable implementation correctly handles both the
rAF-present path and the fallback scheduler branch.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@angular.json`:
- Around line 103-104: The bundle budget thresholds for the initial bundle
(maximumWarning at 5.5mb and maximumError at 6mb) are set too high with
excessive headroom, reducing the effectiveness of regression detection. Reduce
both the maximumWarning and maximumError values to be closer to the actual
current post-change bundle size with only minimal headroom (approximately
50-100kb above the actual size), so that future bundle size regressions will
fail the build quickly and be detected early.

---

Nitpick comments:
In `@src/app/app.component.spec.ts`:
- Around line 132-188: Add a new test case in the removeSsrOverlayWhenStable
describe block to cover the fallback path when requestAnimationFrame is not
available. In this test, delete window.requestAnimationFrame (or set it to
undefined) before constructing the AppComponent, then verify that the
__dspaceRemoveSsrOverlay spy is still called exactly once after the 50ms delay
using fakeAsync, tick, and flush. This ensures the removeSsrOverlayWhenStable
implementation correctly handles both the rAF-present path and the fallback
scheduler branch.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: b4b08381-9c4f-419d-bf0e-0e4c67e443ce

📥 Commits

Reviewing files that changed from the base of the PR and between 31b5313 and 7f23f31.

⛔ Files ignored due to path filters (3)
  • _build.log is excluded by !**/*.log
  • _install.log is excluded by !**/*.log
  • _spec.log is excluded by !**/*.log
📒 Files selected for processing (6)
  • angular.json
  • src/app/app.component.spec.ts
  • src/app/app.component.ts
  • src/index.html
  • src/themes/eager-themes.module.ts
  • src/typings.d.ts

Comment thread angular.json
jr-rk and others added 2 commits June 18, 2026 11:05
The overlay remover bailed out via `if (!el) return;` before unhiding
<ds-app>, so if the overlay node went missing (browser extension, race,
external script) the app stayed visibility:hidden forever -> blank page,
plus the kept SSR styles leaked. Unhide the app and clean up the kept
styles unconditionally, before checking for the overlay node.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
_build.log, _install.log and _spec.log are local deploy-tooling output
that should never have been tracked. Remove them and gitignore /_*.log.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 5 out of 7 changed files in this pull request and generated 1 comment.

Comment thread src/index.html
Make the ApplicationRef.isStable override in the removeSsrOverlayWhenStable
suite configurable and restore the original descriptor in afterEach, so the
patched observable can't leak onto the shared TestBed instance. Add a test
for the requestAnimationFrame-absent fallback branch of the remover.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Propagates VSB-TUO's fix #1317 to this instance. The overlay was removed when
ApplicationRef.isStable settled, but isStable can be delayed for seconds by
post-login admin zone activity (auth work, background polling, third-party
scripts) - during which the live app stays hidden under the SSR mask and the
page renders but is non-interactive (dataquest-dev/dspace-customers#725).

Switch removal to the same condition root.component.html uses to show real
content: !isAuthenticationBlocking && !isThemeLoading. Drop the now-unused
ApplicationRef injection and the 50ms pad; keep the 15s hard fallback as a
catastrophic safety net. Tests and the theme-service mock updated to match.

Ref: #1317

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@jr-rk

jr-rk commented Jun 20, 2026

Copy link
Copy Markdown
Author

Switched the SSR overlay-removal trigger from ApplicationRef.isStable to a content-visible signal (!isAuthenticationBlocking && !isThemeLoading), propagating VSB-TUO's fix #1317.

isStable can stay unsettled for seconds after login (esp. admin: background polling / zone tasks / third-party scripts), leaving the page rendered but non-interactive under the SSR mask — the bug VSB-TUO already hit (dataquest-dev/dspace-customers#725). Applied identically across TUL/SAV/ZCU-DATA/ZCU-PUB so the four stay unified.

@jr-rk jr-rk removed the request for review from milanmajchrak June 23, 2026 07:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants