Compartilhando caches de fragmento de HTML entre usuários com CSS

Por volta dessa época, no ano passado, a 37signals escreveu um ótimo post sobre como o Basecamp Next ficou tão rápido sem usar muita IU do lado do cliente, o que foi um grande recurso para mim no último mês, pois estive trabalhando em um projeto com uma enorme quantidade de dados em cada página que é impossivelmente lenta sem o estilo de cache “boneca russa” de que falam naquele post.

Para aumentar a taxa de acertos do cache e diminuir o tamanho do cache, também segui sua dica de compartilhamento de fragmentos de cache entre usuários. Seu método usa JavaScript para recuperar o ID do usuário de um cookie e ajusta o dom de acordo. Não tenho certeza se esse é o melhor método, ele depende do JavaScript para começar e, dependendo do tamanho do seu aplicativo, significa escrever muito JavaScript para gerenciar as várias coisas que as pessoas devem e não devem ver.

Em vez disso, optei por usar css para ajustar qual conteúdo deve ou não ser mostrado a um usuário. Conforme observado na postagem original, qualquer fragmento html compartilhado entre os usuários deve conter todo o conteúdo (incluindo links para ações que podem ser realizadas) que qualquer usuário individual (incluindo um usuário anônimo) precisa ver.

Para construir o exemplo do 37signals, aqui está um algum html que representa uma postagem que pode ter outros usuários convidados a comentar em uma postagem e outras ações que apenas um usuário específico ou administradores podem executar.

<div id='post-1' class='post'>
<h1 class='title'>My Blog Post</h1>
<div class='content'><p>Lorem ipsum dolar.</p></div>
<form class='invite' action='/posts/1/invite'>
<h4>Invite to comment</h4>
<ul>
<li><input name='invite[1]' type='checkbox'/>User 1</li>
<li><input name='invite[2]' type='checkbox'/>User 2</li>
<li><input name='invite[3]' type='checkbox'/>User 3</li>
</ul>
<input type='submit' value='Invite' />
</form>
<a href='/posts/1/edit'>Edit</a>
<a href='/posts/1/spam'>Mark as spam</a>
<a href='/signin'>Sign in to make changes</a>
</div>

Neste exemplo, queremos que o anônimo veja “faça login para fazer alterações”, os administradores vejam “editar” e “marcar como spam” e o autor da postagem vejam a ação “editar” e “Convidar para comentar”, mas não eles próprios na lista de convidados. E é claro que queremos que todos possam ver o título e o conteúdo.

Supondo que as tags head e body do seu documento não sejam armazenadas em cache, podemos colocar as classes e css que potencializam esse método.

Para um usuário anônimo, a tag body se parece com isto:

<body class='anonymous'>

Para o autor da postagem (nome de usuário: usuário1), a parte superior de seu documento tem a seguinte aparência:

<head>
<style>
.for-user1 { display: block; }
.not-for-user1 { display: block; }
</style>
</head>
<body class='user1 signed-in'>

Para um administrador, a parte superior do documento se parece com isto:

<head>
<style>
.for-user2 { display: block; }
.not-for-user2 { display: none; }
</style>
</head>
<body class='user2 admin signed-in'>

Em seguida, precisamos adicionar algumas classes ao nosso html:

<div id='post-1' class='post'>
<h1 class='title'>My Blog Post</h1>
<div class='content'><p>Lorem ipsum dolar.</p></div>
<form class='invite not-for-most for-user1' action='/posts/1/invite'>
<h4>Invite to comment</h4>
<ul>
<li class='not-for-user1'><input name='invite[1]' type='checkbox'/>User 1</li>
<li><input name='invite[2]' type='checkbox'/>User 2</li>
<li><input name='invite[3]' type='checkbox'/>User 3</li>
</ul>
<input type='submit' value='Invite' />
</form>
<a href='/posts/1/edit' class='not-for-most for-user1 for-admin'>Edit</a>
<a href='/posts/1/spam' class='not-for-most for-admin'>Mark as spam</a>
<a href='/signin' class='for-anonymous'>Sign in to make changes</a>
</div>

E, finalmente, adicione o CSS para potencializar tudo, ele pode ser adicionado a qualquer folha de estilo, mas deve ser adicionado antes de sua tag de estilo que define :.for-user1 { display: block; }

.not-for-most { display: none; }
body
.anonymous .for-signed-in { display: none; }
body
.signed-in .for-anonymous { display: none; }
.for-admin { display: none; }
body
.admin .for-signed-in { display: block; }

Também é possível incluir avatares para o usuário atual. Digamos que tenhamos um formulário de comentário ao lado do qual queremos o avatar do usuário atual (como o Facebook):

<form action='posts/1/comment' class='for-signed-in'>
<img src='/avatars/user1.png' class='avatar' />
<textarea name='comment'></textarea>
<input type='submit' value='Comment' />
</form>

Se mudarmos o html para:

<form action='posts/1/comment' class='for-signed-in'>
<div class='avatar current-user'></div>
<textarea name='comment'></textarea>
<input type='submit' value='Comment' />
</form>

E mude nosso cabeçalho para usuários conectados:

<head>
<style>
.for-user1 { display: block; }
.not-for-user1 { display: none; }
.avatar.current-user { background: url(/avatars/user1.png); }
</style>
</head>
<body class='user1 signed-in'>

E em nossa folha de estilo:

.comment.avatar {
height
: 30px;
width
: 30px;
background
-size: 30px;
}

Obviamente, se a imagem não corresponder às dimensões do avatar e o navegador não suportar o tamanho do plano de fundo (Opera Mini e IE <9), o avatar ficará um pouco engraçado, então acho que neste caso o JavaScript é o melhor opção. Usando nosso formulário de comentário original html (com imgtag, mas com um URL de avatar padrão no src), adicione o seguinte javascript a uma tag de script no final de seu corpo:

$('img.avatar.current_user').attr('src','/avatars/user1.png');