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;
|
||||
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 = {
|
||||
width: 'device-width',
|
||||
initialScale: 1,
|
||||
maximumScale: 1,
|
||||
userScalable: false,
|
||||
maximumScale: 5,
|
||||
userScalable: true,
|
||||
viewportFit: 'cover',
|
||||
themeColor: '#3B82F6',
|
||||
}
|
||||
@@ -66,7 +66,8 @@ export default function RootLayout({
|
||||
<meta name="theme-color" content="#3B82F6" />
|
||||
<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" />
|
||||
</head>
|
||||
<body className="bg-gray-50 min-h-screen">
|
||||
|
||||
@@ -16,6 +16,10 @@ const nextConfig = {
|
||||
productionBrowserSourceMaps: false,
|
||||
trailingSlash: false,
|
||||
poweredByHeader: false,
|
||||
// Optimize for mobile Safari
|
||||
reactStrictMode: true,
|
||||
// Enable optimized font loading
|
||||
optimizeFonts: true,
|
||||
}
|
||||
|
||||
module.exports = nextConfig
|
||||
@@ -60,6 +60,11 @@ self.addEventListener('fetch', (event) => {
|
||||
if (!url.protocol.startsWith('http')) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Skip cross-origin requests for performance
|
||||
if (url.origin !== self.location.origin) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Handle authentication-related requests
|
||||
if (isAuthRequest(url)) {
|
||||
|
||||
Reference in New Issue
Block a user