Desenvolvimento

15 set, 2014

Server-side routes vs. Client-side routes

Publicidade

Lá no SOPT, o usuário Rod fez a seguinte pergunta:

“Qual a vantagem e desvantagem das rotas serem feitas por server(php,asp.net, etc) ou serem por client(angularjs,emberjs,backbone…)? Em relação performance, qual tem maior? Segurança, mobile, usabilidade?”

Achei um assunto bem relevante e resolvi responder.

As rotas são desencadeadores de comportamentos. Quando você acessa http://seusite.com/contato/, a ideia é que seja exibida uma página destinada a contatos. O roteador, neste caso, é o responsável por “explicar” para a aplicação que algum usuário está tentando acessar /contato/ e então algo deve ser feito – neste caso fantasia, o objetivo é exibir a página contato.html, por exemplo.

No caso do JavaScript, independente da plataforma, a ideia é que sejam invocados comportamentos específicos para cada página que o usuário acessar. No nosso exemplo (/contato/), considere que exista um formulário para que o usuário entre com o seus dados. Este formulário, por sua vez, possui uma validação que, no caso do Backbone.js, pode ser resolvido com Backbone.Validation.

Dada a situação, pensamos: seria válido invocarmos o Backbone.Validation para qualquer página, visto que apenas /contato/ possui um formulário?Negativo. Isso é conceitualmente ruim. O roteamento faz justamente isso: desencadeia uma entidade específica para que ela seja responsável por maestrar o que vai ou não acontecer na página solicitada.

Para reforçar, existem dois princípios que se aplicam para este caso: KISS e DRY.

O que são essas “entidades”?

As entidades são os “controllers”, no caso de Angular.js ou Marionette.js; Para Backbone.js, temos as “views” que fazem o serviço.

E a concorrência de cliente com servidor?

Na verdade, a concorrência é relativa. Você pode possuir rotas de cliente e servidor se assim quiser: no cliente você lida com o que a devida rota vai trabalhar em termos de JavaScript; no servidor você lida com o que vai acontecer com o cliente quando tal rota for executada.

Mas, o que isso significa? Se você tiver uma SPA (aplicação de página única), as rotas em cliente são suficiente; se você possuir várias páginas, você (provavelmente) irá trabalhar com roteamento em ambos os lados, tanto cliente quanto servidor, porque indicar o que de JavaScript deve ser executado não será suficiente.

Em relação a performance, qual tem maior? E quanto a segurança, mobile, usabilidade?

O ideal é não comparar a performance das rotas do cliente contra as do servidor – as propostas são diferentes e você tem que optar por aquela que satisfaz (melhor) a sua necessidade.

Você pode controlar todo o roteamento pelo servidor e não utilizar o oferecido pelo cliente: isso, por hora, vai te dar um bootstrap mais produtivo, principalmente se o seu nível de conhecimento sobre as frameworks front-end não for alto; entretanto, por outro lado, vai te gerar um maior número de requisições e a facilidade de escalabilidade do seu aplicativo pode estar comprometida no futuro pela perda de controle e capacidade de manutenção que esse roteamento singular trará.

Como exemplo da empregabilidade paralela dos dois roteamentos, vejamos o GitHub:

  1. Acesse o repositório oficial do Backbone;
  2. Abre o console do seu navegador com, provavelmente, Ctrl + Shift + I ou F12;
  3. Volte o seu foco para o repositório do Backbone;
  4. Clique na pasta “docs“.

Percebeu que foi feita uma requisição do tipo GET e outra do tipo POST e nada foi recarregado? Pois é, o Backbone, por exemplo, traz um conjunto que torna esse mecanismo possível. Começando pelo Backbone.Router, indo até o window.history.

Agora, vou lhe pedir outra coisa: acesse a pasta /docs/ diretamente, emitindo uma requisição síncrona do tipo GET.

Esperando você fazer…

Então, você foi direcionado exatamente para o mesmo lugar que antes, quando você primeiro acessou o repositório e através de um click acabou na pasta /docs/. O que aconteceu é que o roteamento do servidor acabou de cumprir o seu papel — papel esse que um roteador de cliente não assumiria.

Para trabalhar com pushState, eu obrigatoriamente preciso de um roteador no cliente? Roteador é nomenclatura, não algo sólido. A lógica dos roteadores em geral é que você tem que observar uma alteração na URL; se houver uma alteração, então faça algo. Salientando que “se houver uma alteração”, faz parte de roteadores de cliente – roteamento do servidor não tem capacidade de perceber “alterações” em tempo real (como eu disse, coisas diferentes!).

Para ilustrar melhor um roteador, veja o seguinte:

pOAnD

Esse “diagrama” representa o modelo mais comum de roteamento. A princípio, tudo são apenas nomes – o que significa que você pode ter uma estrutura exatamente igual a essa e nunca antes se deu conta. Além disso, obviamente, podem existir outros dispositivos entre os laços dessa trilha – como models, helpers, etc –, mas a diáspora de requisições se move nesse fluxo; nesse sentido.

E quanto a segurança?

Falando de segurança, a premissa é trivial: proteja realmente a sua aplicação no servidor. O cliente é para lidar com informações que as pessoas precisam ver e interagir com elas. Ele jamais deve executar processos lógicos de qualquer porte. De antemão, o cliente deve servir para você mostrar mensagens de erros – o critério por trás dessas mensagens é que deve ser de responsabilidade do servidor: isso é roboticamente imburlável.

Como segurança nunca é demais, você pode juntar o útil ao agradável: faça validações duplex. Tente assegurar o máximo possível no navegador – se caso algo passar em branco ou for burlado, tenha certeza de que o servidor estará à prova de balas. Efeito da ação e reação: validações no cliente exigem mais recursos por parte do usuário. Jamais se esqueça disso.

Ok, e onde entram as rotas + segurança? Ei, calma! A responsabilidade delas é encaminhar pessoas para lugares. A higienização das pessoas que vão passar pelas portas é da responsabilidade de outrem.

… Mobile?

As regras para aplicativos (web) mobile são as mesmas, mas sempre lembrando que as requisições devem ser na menor quantidade possível para garantir uma velocidade de navegação mais satisfatória.

Se você se refere à aplicativos nativos: isso é assunto para um outro artigo!

Para acessar a resposta, eis o link.