37 pontos por GN⁺ 2025-11-03 | 2 comentários | Compartilhar no WhatsApp
  • A estrutura da URL funciona não apenas como um endereço simples, mas como um meio de armazenar e restaurar o estado da aplicação
  • Apresenta o caso da página de download do PrismJS, em que um único URL reproduz completamente as configurações de tema, linguagem e plugins
  • Cada componente, como caminho, parâmetros de consulta e fragmento, expressa diferentes estados, como navegação hierárquica, filtragem e navegação no cliente
  • Filtros de busca, paginação, modo de visualização e intervalo de datas são adequados para inclusão na URL, enquanto informações sensíveis ou estados temporários da UI não são
  • Uma URL bem projetada aumenta a capacidade de compartilhamento, a previsibilidade e a eficiência de cache, reforçando a confiabilidade e a experiência do usuário em aplicações web

O potencial da URL

  • A URL não é apenas o endereço de um recurso, mas também funciona como interface do usuário (UI) e contêiner de estado
    • Ela preserva automaticamente o estado em compartilhamentos, favoritos, histórico do navegador e deep links
    • Desde 1991, atua como o mecanismo básico de gerenciamento de estado da web
  • Cada componente da URL representa um tipo diferente de estado
    • Caminho (Path): navegação hierárquica de recursos (/users/123/posts)
    • Consulta (Query): filtros, opções e configurações (?theme=dark&lang=en)
    • Fragmento (Fragment): posição dentro do documento ou roteamento SPA (#features, #/dashboard)
  • O recurso Text Fragments permite ligar diretamente a um texto específico dentro da página

Padrões de parâmetros de consulta

  • Forma de colocar vários valores em uma única chave usando delimitador (?tags=frontend,react,hooks)
  • Serialização de dados aninhados em JSON ou Base64 (?config=eyJyaWNrIjoicm9sbCJ9==)
  • Flags booleanas expressas pela presença da chave (?mobile)
  • A notação de colchetes (bracket notation) expressa múltiplos valores no formato tags[]=frontend&tags[]=react
    • É reconhecida automaticamente por qs do Node ou middlewares do Express, por exemplo, mas não é padronizada
  • O ponto principal é manter consistência

Exemplos de representação de estado por URL

  • PrismJS: armazena toda a configuração de tema, linguagem e plugins no hash da URL
  • GitHub: destaca um intervalo específico de linhas de código com #L108-L136
  • Google Maps: inclui coordenadas, nível de zoom e tipo de mapa na URL
  • Figma: compartilha o contexto de trabalho, como posição da tela, zoom e elementos selecionados, por URL
  • Sites de e-commerce: incluem filtros, ordenação e faixa de preço na URL para restaurar o estado da busca

Padrões de engenharia de frontend

  • Estados adequados para inclusão na URL
    • termo de busca, filtros, página e ordenação, modo de visualização, intervalo de datas, aba ativa, configuração da UI, flags de funcionalidade
  • Estados inadequados para a URL
    • informações sensíveis como senhas e tokens, estado temporário da UI, entradas não salvas, dados muito grandes, estados de alta frequência
  • Critério de decisão: outro usuário deve ver o mesmo estado ao clicar na mesma URL?

Implementação em JavaScript

  • A API URLSearchParams permite ler e escrever parâmetros de consulta
  • pushState adiciona um novo item ao histórico, e replaceState atualiza o item atual
  • O evento popstate restaura a UI ao usar o botão de voltar do navegador

Implementação em React

  • O hook useSearchParams do React Router permite gerenciar o estado da URL de forma concisa
    • Ao ler e atualizar parâmetros, a URL e a UI são sincronizadas automaticamente

Boas práticas de gerenciamento de estado por URL

  • Não incluir valores padrão na URL (manter apenas ?theme=dark; o valor padrão é tratado no código)
  • Usar debouncing para evitar atualizações excessivas da URL durante a digitação (com lodash.debounce)
  • pushState vs replaceState
    • pushState: para estados reversíveis, como alteração de filtros ou navegação entre páginas
    • replaceState: para ajustes finos, como entrada de busca

Ver a URL como um contrato (Contract)

  • Uma URL bem projetada atua como um contrato explícito entre a aplicação e o usuário
    • Ela deixa claras as fronteiras entre estados públicos/privados, cliente/servidor e compartilhados/de sessão
  • URLs legíveis explicam a intenção e podem ser entendidas tanto por pessoas quanto por máquinas
    • Um formato como example.com/products/laptop?color=silver&sort=price transmite bem o significado
  • Melhora da eficiência de cache
    • A mesma URL é tratada como o mesmo recurso, aumentando a taxa de acerto do cache
    • Parâmetros de consulta podem controlar variações de cache
  • Controle de versão e experimentos
    • ?v=2, ?beta=true, ?experiment=new-ui distinguem versões de API e testes A/B

Antipadrões a evitar

  • Manter estado apenas em memória em SPAs, perdendo o estado ao recarregar a página
  • Incluir informações sensíveis na URL (?password=secret123)
  • Nomes de parâmetros pouco claros (?foo=true&bar=2 em vez de ?mobile=true&page=2)
  • Codificar JSON complexo em Base64, gerando URLs longas demais
  • Ultrapassar o limite de tamanho da URL (há restrições em navegadores, servidores e CDNs)
  • Neutralizar o botão de voltar (isso acontece com uso excessivo de replaceState)

Conclusão

  • Uma boa URL vai além de apontar conteúdo; ela expressa a conversa entre o usuário e a aplicação
  • A URL é um dos meios mais antigos e elegantes de gerenciamento de estado, carregando intenção, contexto e capacidade de compartilhamento
  • Embora existam ferramentas complexas de gerenciamento de estado como Redux, MobX, Zustand e Recoil,
    não esquecer a funcionalidade básica chamada URL é a verdadeira força da web
  • Um app que perde estado ao recarregar está deixando passar uma característica essencial da web

2 comentários

 
GN⁺ 2025-11-03
Comentários do Hacker News
  • Durante code review, tento armazenar o máximo possível de estado (state) na URL
    Ser levado para um lugar completamente diferente após recarregar a página, ou ver uma tela nada a ver ao abrir uma URL compartilhada, é algo ofensivo do ponto de vista do usuário
    Essa abordagem desacelera o desenvolvimento, mas aumenta a percepção de UX dentro da equipe e deixa claro quanto estado estamos colocando na view
    Também existe a preocupação de que a URL vire uma espécie de API pública, criando restrições, mas acho que isso não é um grande problema, já que a maioria das URLs só é usada no curto prazo
    Se necessário, isso pode ser resolvido com código para migrar a URL antiga para a nova no carregamento

    • Gosto dessa abordagem, mas às vezes o autocompletar do histórico do navegador acaba trazendo estados indesejados
      Acho que usar query parameters em vez do path funciona um pouco melhor
    • O webapp corporativo que eu uso criou um botão próprio de “voltar”, e isso quebrou completamente o botão de voltar do navegador
      Do ponto de vista do usuário, a palavra “voltar” está associada ao botão do navegador, então isso gera confusão
      Ter o estado reiniciado ao recarregar incomoda menos, porque existe a noção de que “recarregar = começar de novo”
    • Em páginas renderizadas no servidor, a posição de rolagem é restaurada automaticamente ao recarregar
      Quando tudo é feito em JS, esses recursos básicos acabam quebrando de forma sutil
    • Acho que o design da URL faz parte do design de UX
      Mas, mesmo tendo trabalhado com mais de 30 designers de UX até hoje, nunca recebi orientação sobre URL
    • À medida que a web evoluiu, o significado de recarregar passou a variar conforme o contexto
      Principalmente no mobile, é difícil voltar a página ao estado inicial, então recarregar vira a solução mais rápida
      Em interfaces com rolagem infinita ou filtros complexos, quanto mais estado houver na URL, mais chato fica resetar tudo
      Se o usuário já está insatisfeito com a UX e ainda precisa arrumar a URL, isso vira estresse em dobro
  • Sinto que até pessoas com alta alfabetização digital têm pouca compreensão de URL e DNS
    Elas deveriam ser capazes de reduzir o risco de phishing, entender o significado de parâmetros de URL (?t=_, utm_) e remover informações pessoais antes de compartilhar
    Também deveriam saber que o cadeado do HTTPS não significa ‘confiável’

    • Mas é difícil educar nesse ambiente em que os navegadores por padrão escondem ou abreviam URLs, e as empresas promovem apenas QR codes ou termos de busca
  • Usar a URL como contêiner de estado faz com que a estrutura interna fique exposta e exige versionamento
    Também pode causar problemas de compatibilidade entre navegadores ou nos fluxos de autenticação
    Mesmo assim, tento expor o máximo de estado possível na URL, como se fossem argumentos de linha de comando
    Só que isso é um trade-off intencional, não resultado de ignorância ou falta de experiência

  • Recomendo a biblioteca antiga, mas ainda útil, Rison
    Ela permite armazenar JSON na URL de forma organizada, e também é usada no Kibana da Elastic
    Exemplo: http://example.com/service?query=q:'*',start:10,count:10

    • Era exatamente esse tipo de coisa que eu estava procurando! Antes eu improvisava algo por conta própria, mas isso parece uma forma bem mais padronizada e organizada
  • À medida que o sistema evolui, a estrutura do estado também muda, então colocar estado na URL acaba limitando essa evolução
    Isso acontece porque a URL é, por natureza, uma string permanente
    Em vez disso, acho mais adequado tratar a URL como uma espécie de protocolo, usando formas de codificar e decodificar o estado
    Em páginas simples, até dá para colocar o estado inteiro na URL

    • Em conteúdos com longa vida útil (por exemplo, posts de blog), preservar o estado na URL é útil
      Mas, em casos como feeds, isso depende da expectativa do usuário, como “ao recarregar, deve voltar ao estado mais recente?”
    • Introduzir versionamento pode aliviar esse tipo de problema
  • O limite de tamanho da URL varia conforme navegador, servidor, CDN e configuração de mecanismo de busca, mas em geral fica abaixo de 2000 caracteres
    Fico pensando quanto estado dá para colocar dentro desse limite, ou se seria preciso outra abordagem

    • Excluindo o domínio, cada caractere pode usar 66 possibilidades (maiúsculas, minúsculas, números e os caracteres especiais - . _ ~), então a densidade de informação é bem alta
  • O draw.io consegue armazenar o estado inteiro na URL para compartilhamento
    Os dados do diagrama são codificados em Base64, permitindo restauração completa com um único link
    Só não tenho certeza se isso se encaixa na definição de ‘state container’

  • Eu uso hash routing (#/dashboard) em apps self-hosted
    Como não exige reescrita de URL no servidor (.htaccess etc.), isso reduz as restrições do ambiente de deploy, mesmo não sendo perfeito

  • O Microsoft Teams mais recente trata todas as telas com uma única URL, então é impossível favoritar
    É muito inconveniente não conseguir abrir diretamente um time ou canal específico

  • HATEOAS não chama muita atenção porque o nome não ajuda, mas no fim das contas é um conceito básico da web

    • Do ponto de vista do usuário, seguir links e enviar formulários já é HATEOAS
      Mas, em ambientes em que você controla tanto o servidor quanto o cliente, isso só adiciona complexidade extra
      Principalmente se o cliente ainda precisa conhecer a estrutura dos endpoints, isso só torna a URL opaca
    • Na verdade, esse tema não tem relação direta com HATEOAS. Os dois usam URL, mas HATEOAS não é sobre armazenamento de estado, e sim sobre estrutura de navegação
    • Falando em tom de brincadeira, no fim HATEOAS combina mais com a palavra “cerealization” do que com qualquer outra coisa
 
ndrgrd 2025-11-03

Eu uso bastante o recurso de suspensão de abas, mas em webapps que fixam tudo em uma única URL e se movem como um bloco só, quando entram em suspensão as informações se perdem.

Ao mesmo tempo, essas páginas são todas pesadas, então também não dá para simplesmente desativar a suspensão.