Autosustentabilidade

Recursos Otimizados

Como reduzir tamanho e quantidade de recursos para sustentabilidade.

Por que Otimizar Recursos?

Recursos otimizados reduzem:

  • Dados transferidos: Menos banda consumida
  • Energia de transmissão: Menos energia para transferir dados
  • Tempo de carregamento: Melhor experiência do usuário
  • Custos: Menos custos de banda e servidor

Imagens

Compressão

# 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

Formatos Modernos

<!-- 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>

Responsive Images

<!-- 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">

Lazy Loading

<!-- Carregar apenas quando visível -->
<img 
  src="imagem.jpg" 
  loading="lazy"
  alt="Descrição">

CSS

Minificaçã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}

Remover CSS Não Utilizado

// 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) || []
    })
  ]
};

Critical CSS

<!-- 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'">

JavaScript

Minificação e Tree Shaking

// webpack.config.js
module.exports = {
  optimization: {
    usedExports: true, // Tree shaking
    minimize: true,    // Minificação
    sideEffects: false
  }
};

Code Splitting

// Carregar apenas quando necessário
const HeavyComponent = lazy(() => import('./HeavyComponent'));

Remover Dependências Desnecessárias

# Analisar tamanho de dependências
npx bundle-phobia [package-name]

# Verificar duplicações
npx webpack-bundle-analyzer dist/stats.json

Fontes

Subset de Fontes

/* Carregar apenas caracteres necessários */
@font-face {
  font-family: 'Custom';
  src: url('font-subset.woff2') format('woff2');
  unicode-range: U+0020-007F; /* Apenas ASCII */
}

Font Display

/* 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 de Fontes Críticas

<!-- Preload fonte crítica -->
<link 
  rel="preload" 
  href="font.woff2" 
  as="font" 
  type="font/woff2" 
  crossorigin>

Vídeos

Compressão

# Comprimir vídeo
ffmpeg -i video.mp4 -c:v libx264 -crf 23 -c:a aac -b:a 128k video-compressed.mp4

Formatos Modernos

<!-- Usar formatos modernos -->
<video>
  <source src="video.webm" type="video/webm">
  <source src="video.mp4" type="video/mp4">
</video>

Lazy Loading

<!-- Carregar vídeo sob demanda -->
<video 
  src="video.mp4" 
  preload="none"
  poster="poster.jpg">
</video>

Compressão HTTP

Gzip

# nginx.conf
gzip on;
gzip_types text/plain text/css application/json application/javascript;
gzip_min_length 1000;

Brotli

# Brotli (melhor compressão)
brotli on;
brotli_types text/plain text/css application/json application/javascript;
brotli_comp_level 6;

Cache

Cache de Recursos Estáticos

# Cache longo para recursos estáticos
Cache-Control: public, max-age=31536000, immutable

Versionamento

<!-- Hash no nome do arquivo -->
<script src="app.a1b2c3d4.js"></script>
<link rel="stylesheet" href="styles.b5c6d7e8.css">

CDN

Usar CDN para Recursos Estáticos

<!-- 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>

Checklist de Otimização

  • Imagens comprimidas e em formatos modernos
  • CSS minificado e não utilizado removido
  • JavaScript minificado e tree shaking
  • Fontes com subset e font-display
  • Vídeos comprimidos
  • Compressão HTTP habilitada
  • Cache configurado
  • CDN para recursos estáticos
  • Lazy loading implementado
  • Responsive resources

Exemplo Completo

<!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);
});
Use ferramentas como Lighthouse e WebPageTest para identificar recursos que podem ser otimizados. Foque primeiro nos maiores e mais impactantes.