Recursos otimizados reduzem:
# Comprimir JPEG
convert imagem.jpg -quality 85 -strip imagem-otimizada.jpg
# Comprimir PNG
pngquant --quality=65-80 imagem.png
# Converter para WebP
cwebp -q 80 imagem.jpg -o imagem.webp
<!-- Usar formatos modernos com fallback -->
<picture>
<source srcset="imagem.avif" type="image/avif">
<source srcset="imagem.webp" type="image/webp">
<img src="imagem.jpg" alt="Descrição">
</picture>
<!-- Carregar apenas tamanho necessário -->
<img
srcset="
imagem-400px.jpg 400w,
imagem-800px.jpg 800w,
imagem-1200px.jpg 1200w
"
sizes="(max-width: 600px) 400px,
(max-width: 1200px) 800px,
1200px"
src="imagem-800px.jpg"
alt="Descrição">
<!-- Carregar apenas quando visível -->
<img
src="imagem.jpg"
loading="lazy"
alt="Descrição">
/* Antes */
.button {
background-color: #0066cc;
color: #ffffff;
padding: 10px 20px;
border-radius: 4px;
}
/* Depois */
.button{background-color:#0066cc;color:#fff;padding:10px 20px;border-radius:4px}
// PurgeCSS remove CSS não usado
const purgecss = require('@fullhuman/postcss-purgecss');
module.exports = {
plugins: [
purgecss({
content: ['./src/**/*.html', './src/**/*.js'],
defaultExtractor: content => content.match(/[\w-/:]+(?<!:)/g) || []
})
]
};
<!-- Inline CSS crítico -->
<style>
/* CSS necessário para above-the-fold */
.header { ... }
.hero { ... }
</style>
<!-- CSS não crítico carregado depois -->
<link rel="preload" href="styles.css" as="style" onload="this.onload=null;this.rel='stylesheet'">
// webpack.config.js
module.exports = {
optimization: {
usedExports: true, // Tree shaking
minimize: true, // Minificação
sideEffects: false
}
};
// Carregar apenas quando necessário
const HeavyComponent = lazy(() => import('./HeavyComponent'));
# Analisar tamanho de dependências
npx bundle-phobia [package-name]
# Verificar duplicações
npx webpack-bundle-analyzer dist/stats.json
/* Carregar apenas caracteres necessários */
@font-face {
font-family: 'Custom';
src: url('font-subset.woff2') format('woff2');
unicode-range: U+0020-007F; /* Apenas ASCII */
}
/* Evitar FOIT (Flash of Invisible Text) */
@font-face {
font-family: 'Custom';
src: url('font.woff2') format('woff2');
font-display: swap; /* Mostra fallback enquanto carrega */
}
<!-- Preload fonte crítica -->
<link
rel="preload"
href="font.woff2"
as="font"
type="font/woff2"
crossorigin>
# Comprimir vídeo
ffmpeg -i video.mp4 -c:v libx264 -crf 23 -c:a aac -b:a 128k video-compressed.mp4
<!-- Usar formatos modernos -->
<video>
<source src="video.webm" type="video/webm">
<source src="video.mp4" type="video/mp4">
</video>
<!-- Carregar vídeo sob demanda -->
<video
src="video.mp4"
preload="none"
poster="poster.jpg">
</video>
# nginx.conf
gzip on;
gzip_types text/plain text/css application/json application/javascript;
gzip_min_length 1000;
# Brotli (melhor compressão)
brotli on;
brotli_types text/plain text/css application/json application/javascript;
brotli_comp_level 6;
# Cache longo para recursos estáticos
Cache-Control: public, max-age=31536000, immutable
<!-- Hash no nome do arquivo -->
<script src="app.a1b2c3d4.js"></script>
<link rel="stylesheet" href="styles.b5c6d7e8.css">
<!-- Recursos estáticos via CDN -->
<link rel="stylesheet" href="https://cdn.example.com/css/app.css">
<script src="https://cdn.example.com/js/app.js"></script>
<!DOCTYPE html>
<html lang="pt-BR">
<head>
<!-- Preload recursos críticos -->
<link rel="preload" href="font.woff2" as="font" type="font/woff2" crossorigin>
<link rel="preload" href="critical.css" as="style">
<!-- Critical CSS inline -->
<style>
/* CSS crítico */
.header { ... }
.hero { ... }
</style>
<!-- CSS não crítico -->
<link rel="preload" href="styles.css" as="style" onload="this.onload=null;this.rel='stylesheet'">
</head>
<body>
<!-- Imagem otimizada -->
<picture>
<source srcset="hero.avif" type="image/avif">
<source srcset="hero.webp" type="image/webp">
<img
src="hero.jpg"
alt="Hero"
loading="eager"
fetchpriority="high"
width="1200"
height="600">
</picture>
<!-- JavaScript com defer -->
<script src="app.js" defer></script>
</body>
</html>
// app.js - code splitting
const loadHeavyComponent = async () => {
const { HeavyComponent } = await import('./HeavyComponent');
return HeavyComponent;
};
// Lazy load quando necessário
button.addEventListener('click', async () => {
const Component = await loadHeavyComponent();
renderComponent(Component);
});