UN-3185 [FIX] Deterministic CSS cascade (single bundle) + asset gzip + Edit LLM Profile modal layout#2128
UN-3185 [FIX] Deterministic CSS cascade (single bundle) + asset gzip + Edit LLM Profile modal layout#2128
Conversation
…order Code-splitting (#2114) injects per-route CSS at navigation time, so equal-specificity rules across components resolve in load order — breaking the Edit LLM Profile form and Execution Logs header layout (UN-3185). cssCodeSplit:false restores a single deterministic stylesheet; JS splitting is unaffected. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015DsoHbMN7kTTWwcVC6NNkg
nginx `gzip on` only compresses text/html by default, so JS/CSS shipped uncompressed. Add gzip_types so the single CSS bundle (~341KB -> ~57KB) and all JS chunks compress on the wire — offsets the cssCodeSplit:false upfront cost and speeds every asset. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015DsoHbMN7kTTWwcVC6NNkg
…roll classes Remove settings-body-pad-top + add-llm-profile-scroll-root from the form root (the shared overflow-y:auto added a nested scroll context that #2119 only patched over). The sticky footer now pins directly to .conn-modal-col. Replace the dead override with a :has()-scoped padding so .conn-modal-form-pad-left is adjusted for this panel alone — sibling settings panels and the connector dialog are untouched. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015DsoHbMN7kTTWwcVC6NNkg
nginx skips gzip for proxied requests by default (gzip_proxied off); the GKE load balancer adds a Via header to every request, so static assets shipped uncompressed despite gzip_types. Verified gzip works direct-to-pod. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015DsoHbMN7kTTWwcVC6NNkg
The settings row is hard-fixed at 800px, forcing the form's column (.conn-modal-col) to scroll once Advanced Settings expands. Let the row size to the form so the modal grows instead. Scoped via :has to the LLM profile panel — the other settings panels and the connector dialog share .conn-modal-row/-col and are untouched (so the shared class stays; it is not unused). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015DsoHbMN7kTTWwcVC6NNkg
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
Summary by CodeRabbit
WalkthroughVite build config disables CSS code splitting. The AddLlmProfile modal wrapper and styles change to use ChangesFrontend build and UI layout
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015DsoHbMN7kTTWwcVC6NNkg
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015DsoHbMN7kTTWwcVC6NNkg
|
| Filename | Overview |
|---|---|
| frontend/nginx.conf | Adds gzip compression for CSS/JS/JSON/SVG assets and enables gzip_proxied any for GKE LB. Uses application/javascript which may not match in newer nginx images that serve JS as text/javascript per RFC 9239. |
| frontend/src/components/custom-tools/add-llm-profile/AddLlmProfile.css | Replaces the old overflow workaround with scoped :has() selectors to fix the inner scrollbar on the Edit LLM Profile modal; sticky footer rule is preserved. |
| frontend/src/components/custom-tools/add-llm-profile/AddLlmProfile.jsx | Replaces dual class markers with a single add-llm-profile-body class; a straightforward, minimal JSX change. |
| frontend/vite.config.js | Adds cssCodeSplit: false to merge all CSS into a single deterministic bundle; JS code splitting is unaffected. |
Flowchart
%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[Browser requests page] --> B[GKE Load Balancer adds Via header]
B --> C[nginx]
C --> D{Asset type?}
D -->|assets css| E[Single CSS bundle - cssCodeSplit false - deterministic cascade]
D -->|assets js| F[JS chunks - manualChunks preserved]
D -->|index.html| G[SPA entry - no-cache]
E --> H{gzip_proxied any enabled?}
F --> H
H -->|Yes - Via header no longer skips| I[Compress - content-encoding gzip]
H -->|No - old gzip_proxied off| J[Uncompressed - old behaviour]
I --> K[Browser renders app]
G --> K
style E fill:#d4edda,stroke:#28a745
style I fill:#d4edda,stroke:#28a745
style J fill:#f8d7da,stroke:#dc3545
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
A[Browser requests page] --> B[GKE Load Balancer adds Via header]
B --> C[nginx]
C --> D{Asset type?}
D -->|assets css| E[Single CSS bundle - cssCodeSplit false - deterministic cascade]
D -->|assets js| F[JS chunks - manualChunks preserved]
D -->|index.html| G[SPA entry - no-cache]
E --> H{gzip_proxied any enabled?}
F --> H
H -->|Yes - Via header no longer skips| I[Compress - content-encoding gzip]
H -->|No - old gzip_proxied off| J[Uncompressed - old behaviour]
I --> K[Browser renders app]
G --> K
style E fill:#d4edda,stroke:#28a745
style I fill:#d4edda,stroke:#28a745
style J fill:#f8d7da,stroke:#dc3545
Reviews (2): Last reviewed commit: "fix: drop pre-compressed font types from..." | Re-trigger Greptile
WOFF2 (Brotli) and WOFF (zlib) are already compressed; re-gzipping wastes CPU for no size gain. application/font-woff also never matches nginx's mime.types (.woff -> font/woff), so it was a no-op. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015DsoHbMN7kTTWwcVC6NNkg
Frontend Lint Report (Biome)✅ All checks passed! No linting or formatting issues found. |
|
What
Frontend fixes under UN-3185 (lazy-loading follow-ups), all in
frontend/:cssCodeSplit: false) instead of per-route chunks.gzip_types+gzip_proxied anyinnginx.confso JS/CSS/fonts gzip on the wire.#2119scroll-context workaround, scope the content padding, and remove the inner scrollbar.Why
React.lazychunks, each route's CSS loads as a separate file at navigation time. Equal-specificity rules across components then resolve in load order, which is non-deterministic — breaking the Edit LLM Profile form and overlapping the Execution Logs table header onto the summary cards. Merging CSS into one bundle restores the deterministic order that existed before the split (JS code-splitting — the actual perf win — is unaffected).nginxhadgzip onbut nogzip_types, so onlytext/htmlcompressed; andgzip_proxieddefaults tooff, so even with types listed nothing compressed behind the GKE load balancer (every request carries aViaheader). Assets shipped uncompressed (~341 KB CSS). This offsets the single-bundle's upfront cost and speeds every asset.800px, forcing the form's column (.conn-modal-col) to scroll once Advanced Settings expands.How
vite.config.js:build.cssCodeSplit: false.nginx.conf: addgzip_types(css/js/json/svg/fonts),gzip_min_length,gzip_vary on,gzip_proxied any.AddLlmProfile.jsx/.css: replace the form root's sharedsettings-body-pad-top/add-llm-profile-scroll-rootclasses with a singleadd-llm-profile-bodymarker; drop the deadoverflow: visibleoverride; scope the content padding via:has(); and let the settings row size to the form (:has(.add-llm-profile-body) { height: auto !important }) so the modal grows instead of nesting a scrollbar.Can this PR break any existing features. If yes, please list possible items. If no, please explain why. (PS: Admins do not merge the PR without this section filled)
No.
:has(.add-llm-profile-body), which matches only the Edit LLM Profile form. The shared.conn-modal-row/.conn-modal-col/.conn-modal-form-pad-leftclasses are still used by the other Prompt Studio settings panels and byConfigureConnectorModal(the connector dialog) — none of those carry the marker, so they are untouched. No shared CSS rule was deleted (the classes are still in use, i.e. not unused).cssCodeSplit: falseand thenginxgzip settings are build/serving config; no application behaviour changes.Notes on Testing
chandru-unstract-devnamespace (staging). Verified onchandru.globe.unstract.com: a single/assets/*.cssbundle; assets servedcontent-encoding: gzip(CSS 341 KB → 78 KB on the wire); the scoped:hasrules present in the served bundle.Related Issues or PRs
Checklist
I have read and understood the Contribution Guidelines.