quarta-feira, 31 de outubro de 2012

[JavaScript] JavaScript SideServer!? Isso pode, Arnaldo?

Ainda há pouco estava passeando na Internet, buscando material sobre JavaScript side server quando lembrei, que há muito tempo atrás, entrei em contato com uma iniciativa da antiga Borland, em produzir algo do tipo e vejam o que achei:

Isso deve arrancar nostalgia de alguns. Foi uma excelente ferramenta para o desenvolvimento de páginas dinâmicas para a web, nos idos de 1997/98. Permitia o desenvolvimento de formulários no melhor estilo drag and drop, com um editor muito parecido com o do Delphi. Muito bem feita. Curiosamente teve poucas versões e vida curtíssima. Na Amazon ainda restam 4 unidades do software original para venda. Veja que esta versão é para Windows 95 ou NT e que vinha com o navegador Netscape. Cara!!! Pra quem quiser matar a saudade: 
  • http://www.theopensourcery.com/keepopen/2006/blast-from-the-past-2-borland-intrabuilder/
  • http://alamopc.org/pcalamode/reviews/archive1/rev187.htm
  • http://www.drdobbs.com/borlands-intrabuilder-10/184415559
Bom, recentemente tivemos uma iniciativa da Aptana com o Jaxer, um servidor ajax rodando sobre a máquina do Mozilla. Possuía recursos para escalonamento elástico, preparado para cloud. Com ele era possível marcar um bloco <script> para rodar no cliente, no servidor ou em ambos. Como ele rodava em qualquer container Servlet/JSP, aproveitava recursos da VM para conexão com bancos de dados com prepared statement e tudo mais.

Bem, infelizmente, pouco se encontra do Jaxer hoje na Internet. Muitas outras iniciativas entre o IntraBuilder e o Jaxer aconteceram e curiosamente morreram antes de atingir a maturidade.

Por que alguém anteciparia a aposentadoria de um bom produto a ponto de explodir na indústria e no mercado antes da hora? Por que ninguém quer usar JavaScript fora do navegador?

A bola da vez é o Node.js. Tecnologia JavaScript side server que promete. Já nasce quebrando paradigmas. A idéia de que uma linguagem de programação tem seu sucesso dependendo de sua interação com bancos relacionais é uma delas. Node.js não se propõe a isso. É uma tecnologia para requisições massivas, mais próximo dos No SQL.

No Node.js, do lado do server, para criar uma API RESTful, você importa o módulo http com a instrução require, atribuindo-o a uma variável. Utiliza o método createServer do http para passar uma função anônima que recebe dois parâmetros request e response - há agora sim - e que tem uma propriedade listen, que recebe uma porta. Fica algo assim:

var http = require("http");

http.createServer(function(request, response){
    //Aqui eh a hora do show me the code...
}).listen(80);

Este exemplo é uma API RESTful. O código fica em um arquivo .js e executamos ele chamando o node na linha de comando passando o arquivo como parâmetro. Um servidor será criado ouvindo na porta 80.

O exemplo completo você vê aqui: http://www.ibm.com/developerworks/br/library/os-nodejs/

O Node.js é um paradigma novo, a idéia é um recurso do lado do servidor, rápido, assíncrono e sem bloqueio. Bancos relacionais são síncronos e com bloqueio, logo, Node.js não foi feito para bancos relacionais. O mundo do Node.js é Cloud + No SQL. Sacou?

Forte abraço, até o próximo post.

Mauricio da Silva Marinho

terça-feira, 30 de outubro de 2012

[JavaScript] Onde colocar o script?

Salve salve. Conforme prometido, segue o post (que já estava preparado, mas faz de conta que não), sobre onde colocar o bloco <script> na sua página.

Alguns podem estar se perguntando, mas que importância tem a localização do bloco <script>. Respondo: Muita!

É verdade. Muita coisa pode melhorar ou piorar quanto a performance de execução da sua página a depender da localização do seu javascript, acredite.

Para entender melhor, vamos falar um pouco sobre carga e execução da página.

Como você já sabe, sua página HTML é interpretada e executada pelo seu navegador (sério!?). Ocorre que - regra geral - ao encontrar blocos <script> a execução de HTML é interrompida para que o script seja carregado, interpretado e executado e só então a execução do HTML continua.

Como o processo que executa a página é o mesmo (HTML e JavaScript) - regra geral - não dá pra fazer as duas coisas ao mesmo tempo.

Ainda existe o problema de você carregar um script de manipulação de um elemento DOM antes da declaração do elemento em HTML. O resultado disto é que seu script não poderá manipular o objeto, pois ele ainda não existe, não foi interpretado e muito menos executado pelo browser.

Neste momento, é irrelevante se o código está declarado dentro da tag <script> ou em um arquivo externo .js referenciado no atributo src daquela tag. A página vai ter que esperar até que o código seja baixado, lido e executado.

A especificação do HTML 4 indica que <script> deve ficar em <head> ou <body> e pode aparecer várias vezes dentro destes dois elementos.

Tradicionalmente, as tags <script> são utilizadas para carregar arquivos .js e são posicionadas no <head> junto com tags <link> que carregam arquivos .css.

Pense no seguinte: O HTML só vai começar a ser renderizado, após todos os scripts referenciados serem baixados e executados. Se você permitisse que todo o conteúdo HTML fosse carregado antes dos scripts, talvez pudesse melhorar a percepção de performance da página. Lembre-se que os navegadores não começam a mostrar nada na página (fica em branco) até que cheguem na tag <body>. Se os scripts forem pesados, o delay da página em branco será maior e consequentemente a percepção de lentidão vai aumentar. Observe um exemplo hipotético de página com 3 scripts referenciados em seu <head> e o tempo de carga/execução de cada um deles:

  • arquivo1.js (500ms).
  • arquivo2.js (350ms).
  • arquivo3.js (400ms).

Movendo estas referências para o final da página, você irá ganhar mais de 1s no início da exibição do documento, o suficiente para melhorar a percepção de performance.

IE 8+, Firefox 3.5+, Safari 4+ e Chrome 2+ já permitem o download paralelo dos recursos externos, incluindo outros scripts. Mesmo assim, o download dos scripts irá concorrer com o download de outros recursos visuais da página e o cliclo de vida irá interromper a execução da página até que todos os scripts do <head> sejam executados.

Conclusão: Colocar os scripts mais próximos do rodapé da página, antes de </body>, pode melhorar a performance, este é o posicionamento recomendado, respeitando a ordem de dependência dos scripts. Ah! Muito importante: Mantenha os blocos <script> agrupados e compactados. Várias técnicas de compactação e agrupamento de scripts estão disponíveis, dentre elas a minificaçao e a concatenação de scripts por uma ferramenta de build como o Yahoo combo handler, que permite que você referencia mais de um script em uma mesma tag <script>, mas estes são assuntos para serem explorados em outra oportunidade.

Espero que estes conhecimentos lhe sejam úteis de alguma forma.

Forte abraço,

Mauricio da Silva Marinho.

[JavaScript] Scripts Dinâmicos

[JavaScript] Scripts Dinâmicos.

Com conhecimentos de DOM (Document Object Model) você pode criar praticamente qualquer parte do seu HTML dinamicamente, usando apenas JavaScript. O elemento <script> não é diferente. Referências podem ser recuperadas do DOM, modificadas, removidas ou até mesmo criadas. Um novo elemento <script> pode ser facilmente criado usando métodos do DOM da seguinte forma:

var script = document.createElement("script");
script.type = "text/javascript"; //desnecessario no HTML5
script.src = arquivo1.js;
document.getElementsByTagName("head")[0].appendChild(script);

Este novo elemento <script> carrega o arquivo arquivo1.js. O arquivo começa a ser transferido para o browser tão logo o elemento seja adicionado na página. Vale lembrar que a interpretação do HTML é interrompida cada vez que um elemento <script> é encontrado e retomada após a execução do código em <script>.

O interessante nesta técnica, é que o arquivo é transferido e executado sem bloquear outros processos na página, não importando onde o download tenha sido iniciado. Você pode colocar este código no <head> do documento sem afetar o resto da página.

OBS: Trataremos do melhor lugar para colocar o <script> no próximo post. Por enquanto, é mais seguro colocá-lo no <head> e não no <body>, especialmente se tratamos de um elemento <script> executado durante o carregamento da página. No IE, se o <script> estiver no <body> é possível receber um erro do tipo "operation aborted" se todo o conteúdo do <body> não estiver completamente carregado.

Quando um arquivo é carregado pela criação dinâmica de um nó <script> no DOM, o código transferido, geralmente, é executado imediatamente (ressalvas para o Firefox e Opera, que irão aguardar até que <script>'s anteriores sejam executados.

Isto funciona bem com scripts auto suficientes (sefl-executing), mas podem ser problemáticos se o código contém interfaces para serem usadas por outros scripts na página. Neste caso você precisa rastrear quando o código foi completamente carregado e está disponível para uso. Se não estiver utilizando JQuery, teremos que fazê-lo pelos eventos que podem ser disparados pelo <script>.

Firefox, Opera, Chrome e Safari 3+ disparam um load quando o src de um <script> for recuperado. Você pode programar uma notificação, atribuindo a este evento uma função anônima para ficar ouvindo-o:

var script = document.createElement("script");
script.type = "text/javascript";

//Firefox, Opera, Chrome, Safari 3+
script.onload = function(){
    alert("Script carregado!");
};

script.src = "arquivo1.js";
document.getElementsByTagName("head")[0].appendChild(script);

No IE, bom... no caso do IE, pra variar, é diferente. Este navegador suporta uma implementação alternativa que dispara um evento readystatechange. Existe uma propriedade readyState no <script> que é carregada várias vezes durante a transferência do arquivo referenciado em seu src. Existem cinco possíveis valores para esta propriedade, são eles:

  • uninitialized, que é o default.
  • loading, quando o download do arquivo começa.
  • loaded, quando o download do arquivo termina.
  • interactive, quando os dados já foram baixados mas ainda não estão completamente disponíveis.
  • complete, quando os dados baixados estão prontos para serem utilizados.

O IE mostra-se inconsistente com os valores loaded e complete. Por vezes ele irá atingir o estado loaded e vai parar, sem disparar o complete. Calma que ainda pode piorar: outras vezes ele vai atingir o complete sem passar pelo loaded.

Sendo assim, é preciso tratar os dois estados relevantes para o carregamento loaded e complete, removendo o event handler (a função anônima atribuída ao evento) quando qualquer um deles ocorrer, para evitar de tratarmos duas vezes a mesma coisa (Ê laiá):

var script = document.createElement("script);
script.type = "text/javascript";

//Internet Explorer
script.onreadystatechange = function(){
    if(script.readyState == "loaded" || script.readyState == "complete"){
        script.onreadystatechange = null; //remove o event handler
        alert("Script carregado, eu acho!");
    }
};

Espero que os conhecimentos deste post lhe sejam úteis. No próximo post veremos o melhor lugar para colocar nossos scripts na página. Forte abraço.

Fonte: High Performance Javascript (Build Faster Web Application Interfaces) - Kindle Version, Location 603. Adaptações e sarcasmos de Mauricio da Silva Marinho.