Fix Safari/iPhone performance issues - remove 300ms click delay
- Added touch-action: manipulation CSS to eliminate 300ms tap delay - Optimized service worker to skip cross-origin requests - Updated viewport settings to prevent iOS delays - Added format-detection meta tag - Enabled Next.js performance optimizations - Created comprehensive performance fix documentation
This commit is contained in:
168
SAFARI_PERFORMANCE_FIX.md
Normal file
168
SAFARI_PERFORMANCE_FIX.md
Normal file
@@ -0,0 +1,168 @@
|
|||||||
|
# Safari/iPhone Performance Optimization
|
||||||
|
|
||||||
|
## Issues Fixed
|
||||||
|
|
||||||
|
### 1. 300ms Click Delay (Primary Issue)
|
||||||
|
**Problem**: Safari on iOS has a historical 300ms delay on click events to detect double-tap-to-zoom gestures.
|
||||||
|
|
||||||
|
**Solutions Applied**:
|
||||||
|
- Added `touch-action: manipulation` CSS to all interactive elements (buttons, links, inputs)
|
||||||
|
- Added `format-detection` meta tag to disable automatic phone number detection
|
||||||
|
- Updated viewport to allow user scaling (prevents iOS from adding delays)
|
||||||
|
- Added explicit touch-action rules in globals.css
|
||||||
|
|
||||||
|
### 2. Service Worker Overhead
|
||||||
|
**Problem**: Service worker was intercepting all fetch requests, including cross-origin requests, adding latency.
|
||||||
|
|
||||||
|
**Solutions Applied**:
|
||||||
|
- Added check to skip cross-origin requests in service worker
|
||||||
|
- Service worker now only handles same-origin requests
|
||||||
|
- Reduced unnecessary cache lookups
|
||||||
|
|
||||||
|
### 3. Touch Interaction Optimization
|
||||||
|
**Problem**: Missing touch-specific CSS optimizations for iOS Safari.
|
||||||
|
|
||||||
|
**Solutions Applied**:
|
||||||
|
- Added `-webkit-touch-callout: none` to prevent context menu delays
|
||||||
|
- Added `touch-action: manipulation` to prevent double-tap zoom delays
|
||||||
|
- Optimized tap highlight colors
|
||||||
|
|
||||||
|
### 4. Next.js Configuration
|
||||||
|
**Problem**: Missing performance optimizations in Next.js config.
|
||||||
|
|
||||||
|
**Solutions Applied**:
|
||||||
|
- Enabled `reactStrictMode` for better development debugging
|
||||||
|
- Enabled `optimizeFonts` for faster font loading
|
||||||
|
- Already had compression and minification enabled
|
||||||
|
|
||||||
|
## Testing the Fixes
|
||||||
|
|
||||||
|
### On iPhone Safari:
|
||||||
|
1. Clear Safari cache: Settings > Safari > Clear History and Website Data
|
||||||
|
2. Close all Safari tabs
|
||||||
|
3. Reopen the app
|
||||||
|
4. Test clicking on list cards and navigation links
|
||||||
|
5. Should feel instant now (no 300ms delay)
|
||||||
|
|
||||||
|
### Expected Results:
|
||||||
|
- Links should respond immediately to taps
|
||||||
|
- No delay between tap and navigation
|
||||||
|
- Smooth, native-app-like feel
|
||||||
|
- Faster page transitions
|
||||||
|
|
||||||
|
## Additional Recommendations
|
||||||
|
|
||||||
|
### If Still Experiencing Slowness:
|
||||||
|
|
||||||
|
1. **Check Network Speed**
|
||||||
|
- Open Safari Developer Tools on Mac (Develop > [Your iPhone])
|
||||||
|
- Check Network tab for slow requests
|
||||||
|
- Look for large bundle sizes or slow API calls
|
||||||
|
|
||||||
|
2. **Disable Service Worker Temporarily**
|
||||||
|
- Comment out `<ServiceWorkerRegistration />` in layout.tsx
|
||||||
|
- Test if performance improves
|
||||||
|
- If yes, service worker needs further optimization
|
||||||
|
|
||||||
|
3. **Check for Memory Issues**
|
||||||
|
- Close other Safari tabs
|
||||||
|
- Restart iPhone
|
||||||
|
- Check if other apps are using memory
|
||||||
|
|
||||||
|
4. **Verify Build Optimization**
|
||||||
|
```bash
|
||||||
|
npm run build
|
||||||
|
npm start
|
||||||
|
```
|
||||||
|
- Test production build (much faster than dev mode)
|
||||||
|
|
||||||
|
5. **Enable Safari Debug Console**
|
||||||
|
- Settings > Safari > Advanced > Web Inspector
|
||||||
|
- Connect iPhone to Mac
|
||||||
|
- Safari > Develop > [Your iPhone] > [Your Site]
|
||||||
|
- Check for JavaScript errors or warnings
|
||||||
|
|
||||||
|
## Performance Metrics to Monitor
|
||||||
|
|
||||||
|
### Good Performance Targets:
|
||||||
|
- **First Contentful Paint (FCP)**: < 1.8s
|
||||||
|
- **Time to Interactive (TTI)**: < 3.8s
|
||||||
|
- **Total Blocking Time (TBT)**: < 300ms
|
||||||
|
- **Cumulative Layout Shift (CLS)**: < 0.1
|
||||||
|
- **Largest Contentful Paint (LCP)**: < 2.5s
|
||||||
|
|
||||||
|
### Measure with Lighthouse:
|
||||||
|
```bash
|
||||||
|
# Install Lighthouse CLI
|
||||||
|
npm install -g lighthouse
|
||||||
|
|
||||||
|
# Run audit (with iPhone user agent)
|
||||||
|
lighthouse https://your-app-url --preset=perf --emulated-form-factor=mobile
|
||||||
|
```
|
||||||
|
|
||||||
|
## Changes Made
|
||||||
|
|
||||||
|
### Files Modified:
|
||||||
|
1. `app/layout.tsx` - Updated viewport and meta tags
|
||||||
|
2. `app/globals.css` - Added touch-action CSS rules
|
||||||
|
3. `next.config.js` - Added performance optimizations
|
||||||
|
4. `public/sw.js` - Optimized fetch event handler
|
||||||
|
|
||||||
|
### Key CSS Addition:
|
||||||
|
```css
|
||||||
|
/* Remove 300ms click delay on iOS Safari */
|
||||||
|
a, button, input, select, textarea {
|
||||||
|
touch-action: manipulation;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
This single CSS rule is the most important fix for the click delay issue.
|
||||||
|
|
||||||
|
## Rollback Instructions
|
||||||
|
|
||||||
|
If these changes cause issues:
|
||||||
|
|
||||||
|
1. **Revert viewport changes**:
|
||||||
|
```typescript
|
||||||
|
maximumScale: 1,
|
||||||
|
userScalable: false,
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Remove touch-action CSS**:
|
||||||
|
- Remove the touch-action rules from globals.css
|
||||||
|
|
||||||
|
3. **Revert service worker**:
|
||||||
|
- Remove the cross-origin check in sw.js
|
||||||
|
|
||||||
|
## Further Optimization Ideas
|
||||||
|
|
||||||
|
If you need even better performance:
|
||||||
|
|
||||||
|
1. **Implement Route Prefetching**:
|
||||||
|
- Next.js Link components prefetch by default
|
||||||
|
- Ensure prefetch is not disabled
|
||||||
|
|
||||||
|
2. **Code Splitting**:
|
||||||
|
- Use dynamic imports for heavy components
|
||||||
|
- Lazy load modals and forms
|
||||||
|
|
||||||
|
3. **Image Optimization**:
|
||||||
|
- Use Next.js Image component
|
||||||
|
- Implement lazy loading for images
|
||||||
|
|
||||||
|
4. **Reduce JavaScript Bundle Size**:
|
||||||
|
- Analyze bundle with `npm run build`
|
||||||
|
- Remove unused dependencies
|
||||||
|
- Use tree-shaking
|
||||||
|
|
||||||
|
5. **Implement Virtual Scrolling**:
|
||||||
|
- For long lists of items
|
||||||
|
- Use react-window or react-virtual
|
||||||
|
|
||||||
|
## Support
|
||||||
|
|
||||||
|
If issues persist after these fixes:
|
||||||
|
1. Check browser console for errors
|
||||||
|
2. Test on different iOS versions
|
||||||
|
3. Compare with other devices
|
||||||
|
4. Profile with Safari Web Inspector
|
||||||
@@ -104,4 +104,19 @@ mark {
|
|||||||
-webkit-tap-highlight-color: transparent;
|
-webkit-tap-highlight-color: transparent;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Remove 300ms click delay on iOS Safari */
|
||||||
|
a, button, input, select, textarea {
|
||||||
|
touch-action: manipulation;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Optimize for touch interactions */
|
||||||
|
* {
|
||||||
|
-webkit-touch-callout: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Prevent double-tap zoom on interactive elements */
|
||||||
|
button, a, input[type="button"], input[type="submit"] {
|
||||||
|
touch-action: manipulation;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -34,8 +34,8 @@ export const metadata: Metadata = {
|
|||||||
export const viewport: Viewport = {
|
export const viewport: Viewport = {
|
||||||
width: 'device-width',
|
width: 'device-width',
|
||||||
initialScale: 1,
|
initialScale: 1,
|
||||||
maximumScale: 1,
|
maximumScale: 5,
|
||||||
userScalable: false,
|
userScalable: true,
|
||||||
viewportFit: 'cover',
|
viewportFit: 'cover',
|
||||||
themeColor: '#3B82F6',
|
themeColor: '#3B82F6',
|
||||||
}
|
}
|
||||||
@@ -66,7 +66,8 @@ export default function RootLayout({
|
|||||||
<meta name="theme-color" content="#3B82F6" />
|
<meta name="theme-color" content="#3B82F6" />
|
||||||
<meta name="background-color" content="#ffffff" />
|
<meta name="background-color" content="#ffffff" />
|
||||||
|
|
||||||
{/* iOS Splash Screens - Optional but recommended */}
|
{/* iOS Performance Optimizations */}
|
||||||
|
<meta name="format-detection" content="telephone=no" />
|
||||||
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
|
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
|
||||||
</head>
|
</head>
|
||||||
<body className="bg-gray-50 min-h-screen">
|
<body className="bg-gray-50 min-h-screen">
|
||||||
|
|||||||
@@ -16,6 +16,10 @@ const nextConfig = {
|
|||||||
productionBrowserSourceMaps: false,
|
productionBrowserSourceMaps: false,
|
||||||
trailingSlash: false,
|
trailingSlash: false,
|
||||||
poweredByHeader: false,
|
poweredByHeader: false,
|
||||||
|
// Optimize for mobile Safari
|
||||||
|
reactStrictMode: true,
|
||||||
|
// Enable optimized font loading
|
||||||
|
optimizeFonts: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = nextConfig
|
module.exports = nextConfig
|
||||||
@@ -60,6 +60,11 @@ self.addEventListener('fetch', (event) => {
|
|||||||
if (!url.protocol.startsWith('http')) {
|
if (!url.protocol.startsWith('http')) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Skip cross-origin requests for performance
|
||||||
|
if (url.origin !== self.location.origin) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Handle authentication-related requests
|
// Handle authentication-related requests
|
||||||
if (isAuthRequest(url)) {
|
if (isAuthRequest(url)) {
|
||||||
|
|||||||
Reference in New Issue
Block a user