#performance /
Frontend Performance Optimization Checklist: From 3s to 1s First Screen Load
From a complete frontend performance optimization checklist to practical cases, sharing specific methods to reduce first screen load time from 3 seconds to 1 second.
Goal
Master the core methods of frontend performance optimization and reduce first screen load time from 3 seconds to under 1 second.
Background
Why Is Performance Important?
Google's research data:
- Page load time from 1s to 3s, bounce rate increases 32%
- Page load time from 1s to 5s, bounce rate increases 90%
- Page load time from 1s to 10s, bounce rate increases 123%
Every 100ms delay, conversion rate drops 1%
Performance Metrics
| Metric | Full Name | Meaning | Target | |--------|-----------|---------|--------| | FCP | First Contentful Paint | First content paint | < 1.8s | | LCP | Largest Contentful Paint | Largest content paint | < 2.5s | | FID | First Input Delay | First input delay | < 100ms | | CLS | Cumulative Layout Shift | Cumulative layout shift | < 0.1 | | TTI | Time to Interactive | Time to interactive | < 3.8s |
Optimization Checklist
1. Resource Optimization
Code Splitting
// Route lazy loading
const routes = [
{
path: '/',
component: () => import('@/views/Home.vue')
},
{
path: '/about',
component: () => import('@/views/About.vue')
}
]
// Component lazy loading
const HeavyComponent = defineAsyncComponent(() =>
import('@/components/HeavyComponent.vue')
)
// Dynamic import
const module = await import('./heavy-module.js')
Tree Shaking
// Bad: import entire library
import _ from 'lodash'
_.debounce(fn, 300)
// Good: import only what's needed
import debounce from 'lodash/debounce'
debounce(fn, 300)
// Or use ES Module
import { debounce } from 'lodash-es'
Image Optimization
<!-- Use WebP format -->
<picture>
<source srcset="image.webp" type="image/webp">
<img src="image.jpg" alt="Image">
</picture>
<!-- Responsive images -->
<img
srcset="small.jpg 480w, medium.jpg 800w, large.jpg 1200w"
sizes="(max-width: 600px) 480px, (max-width: 900px) 800px, 1200px"
src="medium.jpg"
alt="Responsive image"
>
<!-- Lazy loading -->
<img loading="lazy" src="image.jpg" alt="Lazy loaded image">
2. Build Optimization
Vite Configuration
// vite.config.ts
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import compression from 'vite-plugin-compression'
export default defineConfig({
plugins: [
vue(),
// Gzip compression
compression({
algorithm: 'gzip',
ext: '.gz'
}),
// Brotli compression
compression({
algorithm: 'brotliCompress',
ext: '.br'
})
],
build: {
// Code splitting
rollupOptions: {
output: {
manualChunks: {
vendor: ['vue', 'vue-router', 'pinia'],
utils: ['lodash-es', 'axios']
}
}
},
// Enable CSS code splitting
cssCodeSplit: true,
// Generate sourcemap
sourcemap: false
}
})
Analyzing Build Results
# Install analysis tool
npm install rollup-plugin-visualizer --save-dev
# Configuration
import { visualizer } from 'rollup-plugin-visualizer'
plugins: [
visualizer({
open: true,
gzipSize: true
})
]
3. Network Optimization
HTTP Caching
# nginx.conf
# Static resources: long-term caching
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff2)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}
# HTML: no caching
location ~* \.html$ {
add_header Cache-Control "no-cache, no-store, must-revalidate";
}
CDN Acceleration
<!-- Use CDN -->
<script src="https://cdn.jsdelivr.net/npm/vue@3.2.0/dist/vue.global.prod.js"></script>
<!-- Preload critical resources -->
<link rel="preload" href="/fonts/main.woff2" as="font" type="font/woff2" crossorigin>
<link rel="preconnect" href="https://cdn.example.com">
HTTP/2
# nginx.conf
listen 443 ssl http2;
4. Rendering Optimization
Critical Rendering Path
<head>
<!-- Inline critical CSS -->
<style>
/* Minimum CSS needed for first screen */
body { margin: 0; font-family: sans-serif; }
.header { height: 64px; background: #fff; }
</style>
<!-- Async load non-critical CSS -->
<link rel="preload" href="/styles/main.css" as="style" onload="this.onload=null;this.rel='stylesheet'">
<noscript><link rel="stylesheet" href="/styles/main.css"></noscript>
</head>
Avoid Layout Shift
/* Set fixed dimensions for images */
img {
width: 100%;
height: auto;
aspect-ratio: 16/9;
}
/* Reserve space for ads */
.ad-container {
min-height: 250px;
}
Reduce Main Thread Work
// Use Web Worker for complex calculations
const worker = new Worker('/worker.js')
worker.postMessage({ data: largeDataSet })
worker.onmessage = (e) => {
console.log('Calculation result:', e.data)
}
// Use requestAnimationFrame for animations
function animate() {
// Animation logic
requestAnimationFrame(animate)
}
requestAnimationFrame(animate)
// Use setTimeout for non-critical tasks
setTimeout(() => {
// Non-critical logic
}, 0)
Practical Case: From 3s to 1s
Before Optimization
Performance metrics:
- FCP: 2.8s
- LCP: 3.2s
- TTI: 4.1s
- Bundle size: 1.2MB (gzipped: 380KB)
Optimization Steps
Step 1: Analyze the Problem
# Use Lighthouse for analysis
npx lighthouse https://example.com --output html
# Use Chrome DevTools Performance panel
# View loading waterfall
Step 2: Code Splitting
// Before: all routes bundled together
import Home from '@/views/Home.vue'
import About from '@/views/About.vue'
import User from '@/views/User.vue'
// After: route lazy loading
const Home = () => import(/* webpackChunkName: "home" */ '@/views/Home.vue')
const About = () => import(/* webpackChunkName: "about" */ '@/views/About.vue')
const User = () => import(/* webpackChunkName: "user" */ '@/views/User.vue')
Step 3: Image Optimization
<!-- Before -->
<img src="hero.jpg" alt="Hero">
<!-- After -->
<picture>
<source srcset="hero.webp" type="image/webp">
<img src="hero.jpg" alt="Hero" loading="lazy" width="1200" height="600">
</picture>
Step 4: Third-party Library Optimization
// Before
import moment from 'moment' // 200KB
moment().format()
// After
import dayjs from 'dayjs' // 2KB
dayjs().format()
Step 5: Enable Compression
# nginx.conf
gzip on;
gzip_types text/plain text/css application/json application/javascript text/xml;
gzip_min_length 1024;
After Optimization
Performance metrics:
- FCP: 0.9s ✓ (reduced 68%)
- LCP: 1.1s ✓ (reduced 66%)
- TTI: 1.8s ✓ (reduced 56%)
- Bundle size: 420KB (gzipped: 120KB)
Monitoring and Alerting
1. Performance Monitoring
// Use Performance Observer
const observer = new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
if (entry.name === 'largest-contentful-paint') {
console.log('LCP:', entry.startTime)
// Report to monitoring system
}
}
})
observer.observe({ type: 'largest-contentful-paint', buffered: true })
// Monitor FID
const fidObserver = new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
console.log('FID:', entry.processingStart - entry.startTime)
}
})
fidObserver.observe({ type: 'first-input', buffered: true })
2. Performance Budget
// performance-budget.json
{
"budgets": [
{
"type": "initial",
"maximumWarning": "200kb",
"maximumError": "300kb"
},
{
"type": "bundle",
"name": "vendor",
"maximumWarning": "100kb",
"maximumError": "150kb"
}
]
}
Common Pitfalls
1. Over-optimization
Don't optimize:
- Microscopic improvements imperceptible to users
- Optimizations that increase code complexity
- One-time performance issues
Worth optimizing:
- Core metrics affecting user experience
- Quantifiable performance improvements
- Long-term maintainable optimization solutions
2. Ignoring Mobile
Mobile characteristics:
- Unstable network
- Weaker CPU performance
- Limited memory
Optimization focus:
- Reduce bundle size
- Optimize image sizes
- Reduce JavaScript execution time
Optimization Checklist
## Frontend Performance Optimization Checklist
### Resource Loading
- [ ] Code splitting (route lazy loading)
- [ ] Image optimization (WebP, responsive)
- [ ] Third-party library on-demand import
- [ ] Font optimization (font-display: swap)
### Build Optimization
- [ ] Enable Gzip/Brotli compression
- [ ] Enable Tree Shaking
- [ ] Analyze bundle size
- [ ] Set performance budget
### Network Optimization
- [ ] Configure HTTP caching
- [ ] Use CDN
- [ ] Enable HTTP/2
- [ ] Preload critical resources
### Rendering Optimization
- [ ] Inline critical CSS
- [ ] Async load non-critical resources
- [ ] Avoid layout shift
- [ ] Reduce main thread work
### Monitoring Alerting
- [ ] Performance metrics monitoring
- [ ] Set performance budget
- [ ] Regular performance audits
Summary
- Performance optimization is a systematic engineering: Needs comprehensive consideration from multiple dimensions
- Data-driven optimization: Measure first, then optimize
- User experience priority: Focus on user-perceived performance metrics
- Continuous optimization: Performance optimization is not a one-time task
- Monitoring is important: No optimization without monitoring
The core of performance optimization is reducing user waiting time. Every optimization point should be decided based on data and user perception.