Skip to content

Commit 8797f57

Browse files
ibrahimcesarclaude
andauthored
Code Review and Quality Check (#159)
* docs: add comprehensive SSR guide and Issue #46 analysis Add detailed documentation to address SSR/Next.js issues reported in #46. Changes: - Add SSR_GUIDE.md: Complete guide for server-side rendering setup - Next.js App Router and Pages Router instructions - Troubleshooting common SSR issues - Performance best practices - SEO optimization patterns - Testing strategies - Add ISSUE_46_RESPONSE.md: Detailed analysis of the 2022 SSR issue - Root cause explanation (React hydration) - Current status (resolved in 2.5.7+) - Clarification about intentional "missing" preconnect links - Proper setup instructions - Testing verification - Update README.md: Add reference to SSR guide in the NextJS section The issue reported in #46 was related to React hydration mismatches in SSR environments and improper CSS imports. The component now works correctly with Next.js 14+ when CSS is properly imported globally. All tests passing (29/29) including click functionality tests. Addresses: #46 * chore: update demo package-lock.json to latest dependencies * chore: remove unnecessary ISSUE_46_RESPONSE.md file --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent cea0ba8 commit 8797f57

File tree

3 files changed

+326
-5
lines changed

3 files changed

+326
-5
lines changed

β€ŽREADME.mdβ€Ž

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,8 @@ const App = () => (
253253
254254
To play nice with new frameworks like [NextJS](https://nextjs.org/), we now don't import the `.css` necessary. Since version `2.0.9` you can pass custom aspect-ratio props, so be aware of any changes needed in the CSS options. Instead use now you have three options:
255255
256+
> **πŸ“˜ Using Next.js or SSR?** Check out the [SSR Guide](./SSR_GUIDE.md) for setup instructions, troubleshooting, and best practices.
257+
256258
### Option 1
257259
258260
Place the necessary CSS in your Global CSS file method of preference

β€ŽSSR_GUIDE.mdβ€Ž

Lines changed: 318 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,318 @@
1+
# Server-Side Rendering (SSR) Guide
2+
3+
This guide addresses common SSR issues with `react-lite-youtube-embed`, particularly for Next.js users.
4+
5+
## Issue #46: Understanding the 2022 SSR Problem
6+
7+
### What Was Reported
8+
9+
Users experienced that clicking the YouTube thumbnail did not trigger video playback when using the component in Next.js with SSR.
10+
11+
### Root Cause
12+
13+
The component uses conditional rendering based on client-side state, which can cause React hydration mismatches:
14+
15+
```typescript
16+
const [preconnected, setPreconnected] = React.useState(false);
17+
18+
// Later in render:
19+
{preconnected && (
20+
<>
21+
<link rel="preconnect" href={ytUrl} />
22+
<link rel="preconnect" href="https://www.google.com" />
23+
</>
24+
)}
25+
```
26+
27+
**During SSR:**
28+
1. Server renders HTML with `preconnected=false` (no preconnect links)
29+
2. HTML is sent to client
30+
3. React hydrates and expects same structure
31+
4. User interaction changes state
32+
5. Potential mismatch can cause React to bail out of hydration
33+
34+
### Current Status
35+
36+
βœ… **The issue should be resolved** in current versions (2.5.7+) as long as you follow the setup instructions correctly.
37+
38+
## Setup for Next.js (App Router)
39+
40+
### 1. Install the Package
41+
42+
```bash
43+
npm install react-lite-youtube-embed
44+
```
45+
46+
### 2. Import CSS Globally
47+
48+
**app/layout.tsx** or **app/globals.css**:
49+
50+
```typescript
51+
import 'react-lite-youtube-embed/dist/LiteYouTubeEmbed.css';
52+
```
53+
54+
### 3. Use the Component
55+
56+
```typescript
57+
import LiteYouTubeEmbed from 'react-lite-youtube-embed';
58+
59+
export default function Page() {
60+
return (
61+
<LiteYouTubeEmbed
62+
id="dQw4w9WgXcQ"
63+
title="Rick Astley - Never Gonna Give You Up"
64+
/>
65+
);
66+
}
67+
```
68+
69+
## Setup for Next.js (Pages Router)
70+
71+
### 1. Import CSS in _app.js
72+
73+
```javascript
74+
// pages/_app.js
75+
import 'react-lite-youtube-embed/dist/LiteYouTubeEmbed.css';
76+
77+
function MyApp({ Component, pageProps }) {
78+
return <Component {...pageProps} />
79+
}
80+
81+
export default MyApp;
82+
```
83+
84+
### 2. Use the Component
85+
86+
```typescript
87+
import LiteYouTubeEmbed from 'react-lite-youtube-embed';
88+
89+
export default function Home() {
90+
return (
91+
<LiteYouTubeEmbed
92+
id="dQw4w9WgXcQ"
93+
title="Rick Astley - Never Gonna Give You Up"
94+
/>
95+
);
96+
}
97+
```
98+
99+
## Troubleshooting SSR Issues
100+
101+
### Issue: "Click doesn't work after SSR"
102+
103+
**Symptoms:**
104+
- Thumbnail loads correctly
105+
- Hover effects work
106+
- Clicking does nothing
107+
108+
**Solutions:**
109+
110+
1. **Verify CSS is loaded:**
111+
```typescript
112+
// Check in browser DevTools that styles are applied
113+
// The .yt-lite class should have proper styling
114+
```
115+
116+
2. **Check for hydration warnings:**
117+
```bash
118+
# Open browser console and look for warnings like:
119+
# "Warning: Text content did not match..."
120+
# "Warning: Prop `%s` did not match..."
121+
```
122+
123+
3. **Use `suppressHydrationWarning` if needed:**
124+
```typescript
125+
// Only if you see hydration warnings
126+
<LiteYouTubeEmbed
127+
id="dQw4w9WgXcQ"
128+
title="Video Title"
129+
// This is a last resort
130+
/>
131+
```
132+
133+
4. **Ensure client-side JavaScript is enabled:**
134+
```typescript
135+
// The component requires JavaScript to work
136+
// Check that Next.js is properly hydrating
137+
```
138+
139+
### Issue: "Missing preconnect links"
140+
141+
**This is by design!** The component intentionally delays preconnecting to YouTube/Google until user interaction (hover) for better performance.
142+
143+
**Why:**
144+
- Reduces initial page load connections
145+
- Only connects when user shows interest
146+
- Privacy-focused (no early tracking)
147+
148+
**The preconnect links appear when:**
149+
1. User hovers over the thumbnail (`onPointerOver`)
150+
2. Before iframe loads
151+
152+
### Issue: "Styles not loading"
153+
154+
**Common causes:**
155+
156+
1. **CSS not imported globally:**
157+
```typescript
158+
// ❌ Wrong - importing in component file
159+
import 'react-lite-youtube-embed/dist/LiteYouTubeEmbed.css';
160+
161+
// βœ… Correct - import in _app.js or layout.tsx
162+
```
163+
164+
2. **CSS import order issues:**
165+
```typescript
166+
// Make sure your global styles don't override the component styles
167+
```
168+
169+
3. **Next.js CSS modules conflict:**
170+
```typescript
171+
// If using CSS modules, ensure they don't conflict
172+
// with .yt-lite, .lty-playbtn classes
173+
```
174+
175+
## Advanced SSR Patterns
176+
177+
### Pre-loading Iframe (Skip Click)
178+
179+
If you want the video iframe to load immediately on SSR:
180+
181+
```typescript
182+
<LiteYouTubeEmbed
183+
id="dQw4w9WgXcQ"
184+
title="Video Title"
185+
alwaysLoadIframe={true}
186+
autoplay={true}
187+
muted={true} // Required for autoplay to work
188+
/>
189+
```
190+
191+
### Custom Thumbnail for Better SSR
192+
193+
Provide a custom thumbnail URL to avoid dynamic thumbnail fetching:
194+
195+
```typescript
196+
<LiteYouTubeEmbed
197+
id="dQw4w9WgXcQ"
198+
title="Video Title"
199+
thumbnail="https://i.ytimg.com/vi/dQw4w9WgXcQ/maxresdefault.jpg"
200+
/>
201+
```
202+
203+
### SEO Optimization for SSR
204+
205+
Add structured data for better SEO:
206+
207+
```typescript
208+
<LiteYouTubeEmbed
209+
id="dQw4w9WgXcQ"
210+
title="Rick Astley - Never Gonna Give You Up"
211+
seo={{
212+
name: "Rick Astley - Never Gonna Give You Up (Official Video)",
213+
description: "The official video for Never Gonna Give You Up",
214+
uploadDate: "2009-10-25T07:00:00Z",
215+
duration: "PT3M33S"
216+
}}
217+
/>
218+
```
219+
220+
This ensures search engines can properly index your videos even with the lite embed.
221+
222+
## Testing SSR
223+
224+
### Test in Development
225+
226+
```bash
227+
npm run dev
228+
# Visit http://localhost:3000
229+
# Disable JavaScript in browser DevTools
230+
# Verify component renders (even without JS)
231+
```
232+
233+
### Test Production Build
234+
235+
```bash
236+
npm run build
237+
npm run start
238+
# Test with JavaScript enabled and disabled
239+
```
240+
241+
### Verify Hydration
242+
243+
```javascript
244+
// Add to your page component for debugging
245+
useEffect(() => {
246+
console.log('Component hydrated and mounted');
247+
}, []);
248+
```
249+
250+
## Performance Best Practices
251+
252+
1. **Use appropriate thumbnail resolution:**
253+
```typescript
254+
// For better performance, use lower resolution thumbnails
255+
<LiteYouTubeEmbed poster="hqdefault" /> // Default
256+
<LiteYouTubeEmbed poster="maxresdefault" /> // Higher quality, larger file
257+
```
258+
259+
2. **Enable WebP format:**
260+
```typescript
261+
<LiteYouTubeEmbed webp={true} />
262+
```
263+
264+
3. **Lazy load below the fold:**
265+
```typescript
266+
// Use Next.js native lazy loading for videos below fold
267+
import dynamic from 'next/dynamic';
268+
269+
const LiteYouTubeEmbed = dynamic(
270+
() => import('react-lite-youtube-embed'),
271+
{ ssr: false } // Skip SSR if needed
272+
);
273+
```
274+
275+
## Common Mistakes
276+
277+
### ❌ Don't Do This
278+
279+
```typescript
280+
// Don't import CSS in component files
281+
import React from 'react';
282+
import LiteYouTubeEmbed from 'react-lite-youtube-embed';
283+
import 'react-lite-youtube-embed/dist/LiteYouTubeEmbed.css'; // ❌ Wrong place
284+
285+
export default function VideoComponent() {
286+
return <LiteYouTubeEmbed id="..." title="..." />;
287+
}
288+
```
289+
290+
### βœ… Do This Instead
291+
292+
```typescript
293+
// Import CSS once in _app.js or layout.tsx
294+
// pages/_app.js
295+
import 'react-lite-youtube-embed/dist/LiteYouTubeEmbed.css'; // βœ… Correct
296+
297+
function MyApp({ Component, pageProps }) {
298+
return <Component {...pageProps} />
299+
}
300+
```
301+
302+
## Still Having Issues?
303+
304+
1. **Check the demo app** - The `/demo` folder contains a working Next.js 14 implementation
305+
2. **Enable verbose logging** - Check browser console for errors
306+
3. **Test without SSR** - Use `ssr: false` to isolate the issue
307+
4. **Report the bug** - Open an issue with:
308+
- Next.js version
309+
- React version
310+
- Browser console errors
311+
- Steps to reproduce
312+
313+
## Related Documentation
314+
315+
- [Next.js CSS Documentation](https://nextjs.org/docs/app/building-your-application/styling/css)
316+
- [React Hydration Documentation](https://react.dev/reference/react-dom/client/hydrateRoot)
317+
- [Component README](./README.md)
318+
- [SEO Guide](./README.md#-seo--search-engine-optimization)

β€Ždemo/package-lock.jsonβ€Ž

Lines changed: 6 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
Β (0)