Voltar para o Blog
Anúncio

Server-First Development: O Futuro com Astro, Remix e SvelteKit

Olá HaWkers, o pêndulo do desenvolvimento web está oscilando novamente. Depois de anos de Single Page Applications (SPAs) dominando o mercado, uma nova abordagem está ganhando tração: Server-First Development.

Frameworks como Astro, Remix e SvelteKit não são apenas alternativas ao React ou Vue — eles representam uma filosofia diferente de como construir para a web. Vamos explorar por que isso importa e como pode transformar a forma como você desenvolve aplicações.

O Que É Server-First Development?

Server-First (ou Server-Centric) não significa abandonar JavaScript do lado do cliente. Significa priorizar o servidor para entregar conteúdo e experiência, usando JavaScript do cliente apenas quando necessário.

Princípios fundamentais:

  1. Render no servidor por padrão: HTML é gerado no servidor, não no browser
  2. JavaScript é progressivo: Adicionado apenas onde melhora a experiência
  3. Performance nativa: Sites carregam rápido sem bundlers pesados
  4. SEO primeiro: Conteúdo acessível sem depender de JavaScript

Isso contrasta com SPAs tradicionais onde você envia um HTML vazio e JavaScript reconstrói tudo no cliente.

<!-- SPA Tradicional (React, Vue) -->
<!DOCTYPE html>
<html>
  <head>
    <title>My App</title>
  </head>
  <body>
    <div id="root"></div>
    <!-- HTML vazio, tudo é renderizado via JS -->
    <script src="/bundle.js"></script> <!-- 200KB+ de JS -->
  </body>
</html>

<!-- Server-First (Astro, Remix, SvelteKit) -->
<!DOCTYPE html>
<html>
  <head>
    <title>My App</title>
  </head>
  <body>
    <!-- HTML completo já no primeiro carregamento -->
    <header>
      <nav>
        <a href="/">Home</a>
        <a href="/about">About</a>
      </nav>
    </header>
    <main>
      <h1>Welcome to My Site</h1>
      <p>This content is immediately visible</p>
    </main>
    <!-- JS mínimo, apenas para interatividade específica -->
    <script src="/interactions.js"></script> <!-- 20KB de JS -->
  </body>
</html>
Anúncio

Astro: Zero JavaScript Por Padrão

Astro adota uma abordagem radical: zero JavaScript no cliente por padrão. Você escolhe explicitamente onde quer interatividade.

---
// src/pages/index.astro
// Código no servidor (Node.js)
const posts = await fetch('https://api.example.com/posts').then(r => r.json());
const currentYear = new Date().getFullYear();
---

<html>
  <head>
    <title>My Astro Site</title>
  </head>
  <body>
    <h1>Blog Posts</h1>

    <!-- Este conteúdo é HTML estático -->
    {posts.map(post => (
      <article>
        <h2>{post.title}</h2>
        <p>{post.excerpt}</p>
        <a href={`/posts/${post.slug}`}>Read more</a>
      </article>
    ))}

    <footer>
      <p>© {currentYear} - Built with Astro</p>
    </footer>
  </body>
</html>

O diferencial: Este código gera HTML estático. Zero JavaScript é enviado ao cliente. O resultado é um site extremamente rápido.

Islands Architecture: Hidratação Parcial

Astro popularizou o conceito de "Islands" — componentes interativos isolados em um mar de HTML estático.

---
// src/pages/products.astro
import StaticHeader from '../components/StaticHeader.astro';
import InteractiveCart from '../components/InteractiveCart.jsx';
import StaticFooter from '../components/StaticFooter.astro';

const products = await getProducts();
---

<html>
  <body>
    <!-- Componente estático - zero JS -->
    <StaticHeader />

    <main>
      <h1>Products</h1>

      <!-- Lista estática - zero JS -->
      {products.map(product => (
        <div class="product">
          <h2>{product.name}</h2>
          <p>${product.price}</p>
        </div>
      ))}

      <!-- Island: Único componente com JS -->
      <InteractiveCart client:load products={products} />
    </main>

    <!-- Componente estático - zero JS -->
    <StaticFooter />
  </body>
</html>

A diretiva client:load ativa JavaScript apenas para InteractiveCart. Tudo mais é HTML estático. Isso resulta em:

  • 93% menos JavaScript comparado a SPAs equivalentes
  • Scores 100/100 no Lighthouse consistentemente
  • TTI (Time to Interactive) abaixo de 1 segundo

astro performance

Framework Agnostic

Astro permite usar React, Vue, Svelte, Solid no mesmo projeto:

---
// Misture frameworks conforme necessário
import ReactCounter from '../components/ReactCounter.jsx';
import VueForm from '../components/VueForm.vue';
import SvelteChart from '../components/SvelteChart.svelte';
---

<html>
  <body>
    <h1>Multi-Framework Page</h1>

    <!-- React component -->
    <ReactCounter client:visible />

    <!-- Vue component -->
    <VueForm client:idle />

    <!-- Svelte component -->
    <SvelteChart client:media="(min-width: 768px)" />
  </body>
</html>

Cada framework é carregado apenas quando necessário. Diretivas como client:visible, client:idle e client:media otimizam ainda mais o carregamento.

Anúncio

Remix: Web Fundamentals Reimaginados

Remix foi construído sobre princípios web fundamentais: formulários HTML, HTTP caching, progressive enhancement.

// app/routes/posts.$postId.tsx
import { json, type LoaderFunctionArgs } from '@remix-run/node';
import { useLoaderData, Form } from '@remix-run/react';

// Loader: Busca dados no servidor
export async function loader({ params }: LoaderFunctionArgs) {
  const post = await getPost(params.postId);

  if (!post) {
    throw new Response('Not Found', { status: 404 });
  }

  return json({ post });
}

// Action: Processa formulário no servidor
export async function action({ request, params }: ActionFunctionArgs) {
  const formData = await request.formData();
  const comment = formData.get('comment');

  await addComment(params.postId, comment);

  return json({ success: true });
}

// Component: Renderiza no servidor e hidrata no cliente
export default function Post() {
  const { post } = useLoaderData<typeof loader>();

  return (
    <article>
      <h1>{post.title}</h1>
      <div dangerouslySetInnerHTML={{ __html: post.content }} />

      <section>
        <h2>Comments</h2>

        {/* Form funciona sem JavaScript! */}
        <Form method="post">
          <textarea name="comment" required />
          <button type="submit">Add Comment</button>
        </Form>

        {post.comments.map(comment => (
          <div key={comment.id}>
            <p>{comment.text}</p>
            <small>{comment.author}</small>
          </div>
        ))}
      </section>
    </article>
  );
}

O que torna Remix especial:

  1. Formulários funcionam sem JS: Progressive enhancement nativo
  2. Data loading otimizado: Parallel data fetching automático
  3. Error boundaries no servidor: Errors são renderizados como HTML
  4. Nested routing: Layouts compartilham dados e UI

Nested Routes e Data Loading

Remix permite nested routes com data loading paralelo:

// app/routes/dashboard.tsx (Layout pai)
export async function loader() {
  const user = await getUser();
  return json({ user });
}

export default function DashboardLayout() {
  const { user } = useLoaderData<typeof loader>();

  return (
    <div>
      <header>Welcome, {user.name}</header>
      <Outlet /> {/* Rotas filhas renderizam aqui */}
    </div>
  );
}

// app/routes/dashboard.projects.tsx (Rota filha)
export async function loader() {
  // Carrega em paralelo com o loader do pai
  const projects = await getProjects();
  return json({ projects });
}

export default function Projects() {
  const { projects } = useLoaderData<typeof loader>();

  return (
    <ul>
      {projects.map(project => (
        <li key={project.id}>{project.name}</li>
      ))}
    </ul>
  );
}

Ambos loaders executam em paralelo, otimizando o carregamento de dados.

Anúncio

SvelteKit: Simplicidade e Performance

SvelteKit combina a simplicidade do Svelte com recursos server-first poderosos.

<!-- src/routes/blog/[slug]/+page.svelte -->
<script lang="ts">
  // Props vêm do loader no servidor
  export let data;
</script>

<article>
  <h1>{data.post.title}</h1>

  <div class="content">
    {@html data.post.content}
  </div>

  <aside>
    <h2>Related Posts</h2>
    {#each data.relatedPosts as post}
      <a href="/blog/{post.slug}">
        {post.title}
      </a>
    {/each}
  </aside>
</article>

<style>
  /* Estilos escopos ao componente */
  article {
    max-width: 800px;
    margin: 0 auto;
  }

  .content {
    line-height: 1.6;
  }
</style>
// src/routes/blog/[slug]/+page.server.ts
import type { PageServerLoad } from './$types';

export const load: PageServerLoad = async ({ params }) => {
  // Executa apenas no servidor
  const post = await getPost(params.slug);
  const relatedPosts = await getRelatedPosts(post.tags);

  return {
    post,
    relatedPosts
  };
};

Vantagens do SvelteKit:

  1. Sem Virtual DOM: Svelte compila para JavaScript imperativo eficiente
  2. File-based routing: Estrutura de arquivos define rotas
  3. Adapters para qualquer plataforma: Deploy em Vercel, Netlify, Node, Cloudflare Workers
  4. Form actions nativas: Manipulação de formulários simplificada

Form Actions: Mutações Sem Complexidade

<!-- src/routes/todos/+page.svelte -->
<script lang="ts">
  export let data;
  export let form; // Resultado da action
</script>

<h1>Todo List</h1>

{#if form?.success}
  <p class="success">Todo added!</p>
{/if}

<!-- Form funciona sem JavaScript -->
<form method="POST" action="?/add">
  <input name="title" required />
  <button>Add Todo</button>
</form>

<ul>
  {#each data.todos as todo}
    <li>
      <span>{todo.title}</span>

      <!-- Delete com JavaScript progressivo -->
      <form method="POST" action="?/delete">
        <input type="hidden" name="id" value={todo.id} />
        <button>Delete</button>
      </form>
    </li>
  {/each}
</ul>
// src/routes/todos/+page.server.ts
import type { Actions, PageServerLoad } from './$types';

export const load: PageServerLoad = async () => {
  const todos = await getTodos();
  return { todos };
};

export const actions: Actions = {
  // Named action: ?/add
  add: async ({ request }) => {
    const data = await request.formData();
    const title = data.get('title');

    await addTodo(title);

    return { success: true };
  },

  // Named action: ?/delete
  delete: async ({ request }) => {
    const data = await request.formData();
    const id = data.get('id');

    await deleteTodo(id);

    return { success: true };
  }
};

Forms funcionam sem JavaScript. Com JavaScript, SvelteKit faz submit via fetch com atualização otimista.

Anúncio

Comparando os Três: Quando Usar Cada Um

Use Astro quando:

  • Conteúdo é prioritário: Blogs, marketing sites, documentação
  • Performance máxima: Cada byte de JavaScript conta
  • SEO é crítico: Sites corporativos, e-commerce
  • Flexibilidade de framework: Time usa React, Vue e Svelte misturados

Exemplo ideal: Blog tech, portfolio, landing pages, documentation sites

Use Remix quando:

  • Aplicações complexas: Dashboards, SaaS, admin panels
  • Forms intensivos: CRUD operations são frequentes
  • Progressive enhancement: Aplicação deve funcionar sem JS
  • Ecossistema React: Time já domina React

Exemplo ideal: Admin dashboards, e-commerce platforms, SaaS applications

Use SvelteKit quando:

  • Produtividade rápida: Time pequeno, deadlines apertados
  • Aplicações full-stack: Backend e frontend integrados
  • Performance e simplicidade: Quer melhor de ambos os mundos
  • Deployment flexível: Pode precisar mudar de plataforma depois

Exemplo ideal: MVPs, startups, aplicações full-stack rápidas

Edge Computing e o Futuro

Todos três frameworks abraçam edge computing — código roda perto do usuário, não em servidores centralizados.

// Exemplo: Edge function no SvelteKit (Cloudflare Workers)
// src/routes/api/geo/+server.ts
export const GET = async ({ request }) => {
  // Código roda no edge, perto do usuário
  const country = request.headers.get('cf-ipcountry');
  const city = request.headers.get('cf-ipcity');

  return new Response(
    JSON.stringify({
      country,
      city,
      message: `Hello from the edge in ${city}, ${country}!`
    }),
    {
      headers: { 'Content-Type': 'application/json' }
    }
  );
};

Edge functions reduzem latência drasticamente, especialmente para usuários globais.

edge computing

O Renascimento do Server-Side Rendering

Server-First não é um passo atrás — é evolução. Pegamos o melhor de SPAs (experiência rica, interatividade) e o melhor de sites tradicionais (performance, SEO, simplicidade).

O resultado são aplicações que:

  • Carregam instantaneamente
  • Funcionam sem JavaScript
  • Escalam globalmente via edge
  • São mais simples de desenvolver e manter

Se você está começando um novo projeto em 2025, considere seriamente um destes frameworks. O futuro da web é server-first.

Quer entender os fundamentos de JavaScript que tornam esses frameworks possíveis? Confira meu artigo sobre Programação Funcional em JavaScript onde você vai descobrir padrões que Astro, Remix e SvelteKit utilizam internamente.

Bora pra cima! 🦅

📚 Quer Aprofundar Seus Conhecimentos em JavaScript?

Este artigo cobriu frameworks server-first modernos, mas há muito mais para explorar no mundo do desenvolvimento moderno.

Desenvolvedores que investem em conhecimento sólido e estruturado tendem a ter mais oportunidades no mercado.

Material de Estudo Completo

Se você quer dominar JavaScript do básico ao avançado, preparei um guia completo:

Opções de investimento:

  • 3x de R$34,54 no cartão
  • ou R$97,90 à vista

👉 Conhecer o Guia JavaScript

💡 Material atualizado com as melhores práticas do mercado

Anúncio
Post anteriorPróximo post

Comentários (0)

Esse artigo ainda não possui comentários 😢. Seja o primeiro! 🚀🦅

Adicionar comentário