Há cerca de um ano, foi publicado o artigo manifesto de Nikita Prokopov sobre decepção em software. A julgar pelo feedback positivo, os desenvolvedores não são indiferentes à qualidade de seus produtos. Talvez seja hora de começar a atuar?
Neste artigo, quero falar sobre o meu desenvolvimento, que, na minha opinião, pode curar os principais problemas de desempenho da web moderna e tornar o usuário um pouco mais feliz. Os problemas são: código JS pesado, tempo para começar a trabalhar com a página (TTI) , alto consumo de memória e processador.
Antes de ler mais, siga o link . Tente jogar alguns jogos. Jogue preferencialmente na área de trabalho.
Um pouco de história
Desde o início, o navegador da web foi concebido como um thin client para servidores da web. O navegador exibiu as páginas de hipertexto que recebeu do servidor. Simples e elegante. Como geralmente acontece, uma bela idéia é confrontada com a realidade e, após alguns anos, os fabricantes de navegadores adicionaram suporte à linguagem de script. No início, servia apenas como decoração e, até meados da década de 2000, era considerado uma boa forma de fazer as páginas da web funcionarem sem o suporte a JS.
Uma abordagem moderna para o desenvolvimento de sites é o resultado do desenvolvimento de requisitos de interatividade da interface do usuário. Tarefas para melhorar a interatividade caíram sobre os ombros dos codificadores. Aqueles geralmente não tinham as competências e autoridade para desenvolver uma solução "de ponta a ponta". Os designers de layout aprenderam a escrever JS e se tornaram front-end. A lógica começou gradualmente a fluir do servidor para o cliente. É conveniente que o front-run escreva para o navegador, e o back-end é conveniente para não pensar no usuário (forneça meu JSON para você e, pelo menos, a grama não crescerá). Apenas dois anos atrás, houve um aumento no interesse pela arquitetura sem servidor, onde foi sugerido que os aplicativos JS funcionassem diretamente com o banco de dados e os barramentos de eventos.
Atualmente, um "site esférico no vácuo" é um aplicativo JS complexo e um servidor API simples com o qual ele se comunica. A lógica principal é executada em um cliente espesso, o lado do servidor degenera para uma camada simples no banco de dados.
A necessidade de manter a lógica no cliente cria problemas. Se o serviço "decolou" e começou a ganhar dinheiro, ainda mais em termos de produtividade, só piorará. Os requisitos mudarão. A equipe de desenvolvimento mudará. Haverá mais e mais novos códigos, e o código antigo não será limpo. A página aumentará a partir de dependências, carregará o JSON com o objetivo de que ninguém se lembra, mas é assustador excluir, de repente algo quebra. Aparecerão as tarefas em segundo plano SetInterval, cada uma delas realizada por vários milissegundos a cada segundo, o que, após algum tempo, levará a freios e aquecerá o iPad do usuário infeliz, a ponto de ele poder fritar ovos fritos. Isso termina com o fato de o front-end queimado chegar ao gerente com uma proposta para reescrever tudo do zero em uma nova estrutura. O gerente recusará e o front-end começará a usar duas estruturas juntas.
Como funciona o Korolev
Então, e se voltarmos ao ponto do relatório? O momento em que alguém teve a idéia de atualizar o conteúdo sem recarregar a página e a inevitabilidade histórica deu origem ao AJAX? E se você deixar tudo no servidor e criar um thin client? Os melhores sites fazem a pré-renderização da página do servidor (SSR) para que o usuário veja a interface antes que o JS seja carregado e iniciado. Você pode ir além e deixar no cliente apenas o código responsável pelo processamento de E / S, considerando os requisitos atuais de interatividade. Pensamentos sobre isso se espalharam para o projeto Korolev .
Como isso funciona no lado do cliente? O usuário chega à página. O servidor fornece o HTML gerado e um pequeno script (~ 6 Kbytes sem compactação) que se conecta ao servidor por meio de um soquete da web. Quando um usuário aciona um evento (por exemplo, um clique), o script o envia ao servidor. Após o processamento do evento, o servidor gera uma lista de comandos no formato "adicione um novo <div>
lá", "adicione uma classe a esse elemento", "exclua esse e esse elemento". O cliente aplica a lista de comandos ao DOM. Como tal, o trabalho com HTML não ocorre - o script funciona diretamente com o DOM, portanto, não se preocupe, pois o conteúdo do formulário ou a posição da rolagem serão redefinidos.
O que está acontecendo no servidor? Quando uma solicitação de página vem do navegador, Korolev cria uma nova sessão. Para a sessão, é feito o estado inicial, que é armazenado no cache. O HTML é gerado a partir desse estado, que é fornecido ao cliente como uma resposta à solicitação. Além disso, o servidor salva o "DOM virtual" na sessão. Após solicitar a página, o servidor aceita a solicitação para abrir o soquete da web. Korolev associa um soquete da web aberto a uma sessão. Cada evento proveniente do cliente pode alterar o estado associado à sessão. Cada alteração de estado leva a uma chamada para a função de render
, que forma um novo "DOM virtual", que é comparado com a versão antiga. A comparação resulta em uma lista de comandos para enviar ao cliente.
O que acontece no código e no chefe do desenvolvedor? O exemplo acima pode lembrá-lo do React, com a diferença de que tudo é executado no servidor. Em termos de abordagem de desenvolvimento, também temos algo semelhante. Portanto, se você trabalhou com o React ou outro "DOM virtual", a abordagem da rainha será familiar para você. Se você não estiver familiarizado com o React, imagine que possui dados inseridos no modelo. Imagine que, de acordo com o modelo, os manipuladores de eventos estejam dispersos e possam alterar dados (mas não o DOM). Você altera os dados, a página muda automaticamente. O próprio Korolev propõe como alterar o DOM.
Desempenho
Há duas perguntas populares sobre Korolev: "e se os atrasos forem altos" e "isso não carregará meu servidor"? Ambas as perguntas são muito razoáveis. O programador front-end está acostumado a executar o programa na máquina local do usuário. Isso significa que as alterações feitas serão aplicadas assim que a máquina JS concluir a execução do código e o navegador iniciar a renderização. Eu mostrei especificamente um exemplo de uso "na velocidade máxima" no início. Você pode observar o atraso apenas se você veio do outro lado do mundo (os servidores estão localizados em Moscou) ou se sentou na Internet via GPRS. Bem, ou o meu patético servidor virtual com um núcleo e 1 GB de RAM não suportou o efeito habr.
A pergunta sobre a carga do servidor é geralmente feita por beckenders. O mecanismo de saída de alterações funciona muito rapidamente: ~ 10 mil conclusões por segundo para duas árvores arbitrárias de 500 nós no macbook junior de 2013. A renderização estática também fornece um resultado muito bom: até 1 milhão de páginas por segundo. Cada "DOM virtual" é armazenado e processado em um formato serializado especial e leva 128 KB para uma página da Web comum. O processo de saída é especialmente otimizado e não possui uma sobrecarga de memória e GC.
Quanto à velocidade do desenvolvimento, aqui Korolev oferece grandes vantagens. Não há necessidade de escrever uma camada adicional entre o banco de dados e o servidor. Não há necessidade de negociar um protocolo entre cliente e servidor. Não precisa se preocupar com a modularidade do front-end - o peso do JS no cliente sempre permanecerá o mesmo. Não há necessidade de fazer lógica adicional para eventos do servidor: basta aceitar a mensagem da fila e alterar o estado da sessão, o Korolev renderizará e entregará.
Preço
Você tem que pagar pelos benefícios. Alguns hábitos terão que ser abandonados e outros novos a serem adquiridos. Por exemplo, você deve abandonar as animações JS e ficar satisfeito com as animações CSS. Você precisará aprender como tornar a infraestrutura inicialmente distribuída geograficamente, se desejar atender usuários de diferentes países com alta qualidade. Tem que abandonar JS e ir para Scala.
Estou um pouco envergonhado (na verdade não) por ter enganado o leitor e não disse imediatamente que Korolev foi escrito em Scala. Você leria até este ponto se eu falasse imediatamente sobre isso? Falando sobre a rainha, tenho que superar dois estereótipos. O primeiro se deve ao fato de a renderização do servidor ser percebida como algo lento, não interativo. O segundo está relacionado ao fato de Scala ser algo complicado. E o primeiro e o segundo estereótipos não têm nada a ver com a realidade. Além disso, a programação no estilo React no Scala é mais conveniente do que no JS. O JS moderno gravita em direção à programação funcional, o Scala o tira da caixa. Por exemplo, qualquer objeto no Scala possui um método copy()
que permite copiar um objeto alterando alguns campos. Coleções imutáveis são construídas na biblioteca padrão do Scala.
Conclusão
O Korolev foi desenvolvido por três anos por vários desenvolvedores e muitos problemas "infantis" foram resolvidos. O projeto está bem documentado, todas as funcionalidades são cobertas com exemplos. Proponho começar a implementação da rainha com pequenos serviços independentes. Espero que Korolev ajude a tornar os programas menos decepcionantes.
Link para o projeto no github