
preload/prefetch)http {
gzip on; gzip_types text/css application/javascript application/json image/svg+xml;
gzip_min_length 1024;
brotli on; brotli_types text/css application/javascript application/json image/svg+xml;
}
server {
location /assets/ {
add_header Cache-Control "public, max-age=31536000, immutable";
}
}// vite.config.ts
export default {
build: {
rollupOptions: {
output: {
manualChunks: {
vendor: ['vue','react'],
ui: ['element-plus','antd'],
chart: ['echarts','chart.js']
}
}
}
}
}const route = { path: '/', component: () => import('./pages/Home.vue') }import { defineAsyncComponent } from 'vue'
const AsyncChart = defineAsyncComponent(() => import('./Chart.vue'))<img src="hero.avif" width="1200" height="800" alt="hero" loading="lazy" />preload:<link rel="preload" as="image" href="/images/hero.avif" imagesrcset="/images/hero-640.avif 640w, /images/hero-1200.avif 1200w" imagesizes="(max-width: 640px) 640px, 1200px" />@font-face { font-family: 'InterSubset'; src: url('/fonts/inter-subset.woff2') format('woff2'); font-display: swap; }<style>/* critical above-the-fold CSS */</style>
<link rel="preload" as="style" href="/assets/main.css" onload="this.rel='stylesheet'" />
<noscript><link rel="stylesheet" href="/assets/main.css" /></noscript>defer/async:<script src="/assets/app.js" defer></script><link rel="preconnect" href="https://cdn.example.com" />
<link rel="prefetch" href="/assets/chart.js" as="script" />content-visibility: auto.hero, .section { content-visibility: auto; contain-intrinsic-size: 800px }export async function fetchWithTimeout(p: Promise<any>, ms=1500){
return Promise.race([p, new Promise((_,rej)=>setTimeout(()=>rej(new Error('timeout')), ms))])
}immutable;HTML 不缓存loading=lazy、首屏 preloadfont-display: swappreconnect/preload/prefetchdefer/async,避免阻塞;事件委托与节流content-visibilitypreload 导致拥塞:仅关键资源使用;其余用 prefetchpreload+响应式;非首屏 loading=lazy