-
-
Notifications
You must be signed in to change notification settings - Fork 638
Remove gap in page lifecycle check for setup listeners #1773
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Remove gap in page lifecycle check for setup listeners #1773
Conversation
Co-authored-by: justin808 <[email protected]>
Code Review Feedback✅ Overall Assessment: Good ChangeThis PR makes a targeted improvement to support async scripts in React on Rails v15. The core change is sound and well-motivated. 📋 Code Quality & Best PracticesPositive aspects:
Minor improvements:
🐛 Potential IssuesTest implementation concerns:
⚡ Performance ConsiderationsPositive impact:
🔒 SecurityNo security concerns identified - This change only affects timing of event listener setup. 🎯 Implementation NotesThe core change is correct:
This aligns with modern web performance best practices and supports the stated goal of async script compatibility. 📊 Recommendations
🔍 Missing Elements
Overall: ✅ Approve - This is a well-thought-out change that addresses a real need for async script support while maintaining backward compatibility. |
Code Review for PR #1773: Fix page lifecycle to support async scriptsOverall, this is a well-thought-out change that addresses a real need for better async script support. The logic is sound and the implementation is clean. Here's my detailed feedback: ✅ Strengths
🔍 Code Quality & Best PracticesCore Implementation (
|
Code ReviewSummaryThis PR fixes an important timing issue in the page lifecycle initialization by changing from ✅ StrengthsCode Quality
Testing
🔍 Areas for ImprovementTest Implementation IssuesHigh Priority: Test Logic Gaps
Suggested improvement: // Better test approach - directly test the function behavior
import * as pageLifecycle from '../src/pageLifecycle.ts';
// Mock the setupPageNavigationListeners function directly
const mockSetupPageNavigationListeners = jest.fn();
jest.mock('../src/pageLifecycle.ts', () => ({
...jest.requireActual('../src/pageLifecycle.ts'),
setupPageNavigationListeners: mockSetupPageNavigationListeners
}));Minor Code ConsiderationsPerformance: The change actually improves performance by initializing earlier - this is positive. Security: No security concerns - the change reduces wait time but doesn't introduce new attack vectors. Browser Compatibility: The 🎯 Specific Recommendations1. Strengthen Test Verificationit('should call setupPageNavigationListeners immediately when readyState is interactive', async () => {
Object.defineProperty(document, 'readyState', {
value: 'interactive',
writable: true
});
const { initializePageEventListeners } = require('../src/pageLifecycle.ts');
const setupSpy = jest.spyOn(pageLifecycle, 'setupPageNavigationListeners');
initializePageEventListeners();
// Directly verify the function was called
expect(setupSpy).toHaveBeenCalledTimes(1);
});2. Add Integration TestConsider adding an integration test that verifies the actual timing behavior with a real DOM scenario. 3. Documentation UpdateThe change is significant enough to warrant a mention in the changelog or migration notes for v15. 🚀 Performance ImpactPositive: Earlier initialization means faster time-to-interactive, especially beneficial for:
✅ Final VerdictThis is a well-conceived fix that addresses a real timing issue. The core change is solid and the comprehensive testing approach shows attention to detail. With minor test improvements, this will be a valuable enhancement for React on Rails v15. Approval: ✅ Approve with minor test refinements suggested above. Review generated with attention to the project's focus on Rails-React integration and async script support. |
Code Review✅ Overall Assessment: LGTM with Minor SuggestionsThis is a well-thought-out change that addresses a real performance issue with async script loading in React on Rails v15. The modification is minimal, focused, and well-documented. Code Quality & Best PracticesStrengths:
Technical Review:
Test CoverageStrengths:
Suggestions for Test Improvement:
Security & ReliabilityStrengths:
Performance ImpactStrengths:
Impact Analysis:
Minor Suggestions
Compatibility & IntegrationAnalysis:
RecommendationApprove and merge - This change successfully addresses async script loading issues while maintaining backward compatibility and adding appropriate test coverage. The minor test improvements suggested above are optional and don't block merging. Priority: This appears to be an important performance improvement for v15 users, especially those using async scripts. |
…and improve test isolation - Mocked turbolinksUtils module to simulate different navigation library scenarios. - Added tests for Turbo, Turbolinks 5, and Turbolinks 2 event listeners. - Improved test structure for better isolation and dynamic module loading. - Included tests for handling multiple callbacks and server-side rendering scenarios. - Ensured that event listeners are not initialized multiple times.
|
Important Review skippedBot user detected. To trigger a single review, invoke the You can disable this status message by setting the Comment |
Code Review: Fix page lifecycle to support async scripts in React on Rails v15Overall Assessment ✅This is a well-implemented fix that addresses a real performance and compatibility issue. The change is minimal but impactful, improving async script support while maintaining backward compatibility. Code Quality & Best Practices ✅Strengths:
Suggestions:
Potential Issues ❌ None FoundNo bugs identified. The logic is sound:
Performance Considerations ✅Excellent performance improvement:
Security Concerns ✅ NoneNo security implications. This change only affects timing of initialization and does not introduce new attack vectors or expose sensitive data. Test Coverage ✅ ExcellentComprehensive test suite covers all scenarios:
Test quality is high:
Minor Suggestions
Final Recommendation: ✅ APPROVEThis is a high-quality fix that:
The change is ready to merge. Great work on identifying and fixing this async script compatibility issue! |
AbanoubGhadban
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch by Copilot—Judah was already planning to do it, but AI got there first.
Here are my notes on the PR:
- The PR title and description are misleading. It doesn’t actually add support for async scripts—React on Rails v15 already supports them. In fact, components can hydrate very early, even before the page loads, if
force_loadis enabled. - In practice, it doesn’t matter whether scripts are marked as
asyncordefer; theinteractivestate is only reached after all deferred scripts finish executing. Judah’s original phrasing, Remove gap in page lifecycle check for setup listeners, better describes the change. - The tests that were added weren’t asserting anything. I had to rewrite them to properly verify the page lifecycle.
Previously,
setupPageNavigationListenersonly ran after all JS finished loading. In v15, React on Rails introduced proper support for async component registration and hydration.Note
React on Rails v15 enables the
force_loadfeature by default, which hydrates components as soon as both their HTML (first chunk in the case of streamed components) and JS are loaded—even if the JS is loaded via anasyncscript.These force-loaded components are unaffected by this change. The improvement applies to non-force-loaded components, which some apps may still keep deferred until after the page has fully loaded (for backward compatibility or other reasons).
The Problem
In
pageLifecycle.ts,setupPageNavigationListeners()only ran whendocument.readyState === 'complete'. This delayed hydration of non-force-loaded components until all resources (images, stylesheets, etc.) were finished loading—causing unnecessary lag.The Solution
Update
initializePageEventListeners()to checkdocument.readyState !== 'loading'instead of=== 'complete'. This ensures setup runs when the document is eitherinteractiveorcomplete.Before:
After:
Why This Matters
document.readyStatehas three values:'loading'– still parsing the document'interactive'– DOM is parsed, but subresources may still load'complete'– all resources are fully loadedBy moving from
=== 'complete'to!== 'loading', we now initialize in bothinteractiveandcompletestates, which provides:💬 Share your feedback on Copilot coding agent for the chance to win a $200 gift card! Click here to start the survey.
This change is