Node.js - Construção de Aplicações Web

Page 1

Capa - Node.JS Introdução.pdf

C

M

Y

CM

MY

CY

CMY

K

1

02/11/16

09:54


EDIÇÃO FCA – Editora de Informática, Lda. Av. Praia da Vitória, 14 A – 1000-247 Lisboa Tel: +351 213 511 448 fca@fca.pt www.fca.pt DISTRIBUIÇÃO Lidel – Edições Técnicas, Lda. Rua D. Estefânia, 183, R/C Dto. – 1049-057 Lisboa Tel: +351 213 511 448 lidel@lidel.pt www.lidel.pt LIVRARIA Av. Praia da Vitória, 14 A – 1000-247 Lisboa Tel: +351 213 511 448 * Fax: +351 213 522 684 livraria@lidel.pt Copyright © 2016, FCA – Editora de Informática, Lda. ISBN edição impressa: 978-972-722-860-7 1.ª edição eBook: abril 2016 1.ª edição impressa: novembro 2016 Impressão e acabamento: Realbase – Soluções Informáticas, Lda. Depósito Legal n.º 417009/16 Capa: José M. Ferrão – Look-Ahead

Marcas Registadas de FCA – Editora de Informática, Lda. –

®

®

®

Todos os nossos livros passam por um rigoroso controlo de qualidade, no entanto aconselhamos a consulta periódica do nosso site (www.fca.pt) para fazer o download de eventuais correções. Não nos responsabilizamos por desatualizações das hiperligações presentes nesta obra, que foram verificadas à data de publicação da mesma. Os nomes comerciais referenciados neste livro têm patente registada. Reservados todos os direitos. Esta publicação não pode ser reproduzida, nem transmitida, no todo ou em parte, por qualquer processo eletrónico, mecânico, fotocópia, digitalização, gravação, sistema de armazenamento e disponibilização de informação, sítio Web, blogue ou outros, sem prévia autorização escrita da Editora, exceto o permitido pelo CDADC, em termos de cópia privada pela AGECOP – Associação para a Gestão da Cópia Privada, através do pagamento das respetivas taxas.


Este livro ĂŠ dedicado Ă minha esposa, Marina.



ÍNDICE GERAL AGRADECIMENTOS ...............................................................................................XI SOBRE O LIVRO .............................................................................................. XIII O que posso encontrar neste livro?......................................................................................................XIII Requisitos ................................................................................................................................................XIII A quem se dirige este livro? ................................................................................................................ XIV Convenções .............................................................................................................................................. XV Organização do livro .............................................................................................................................. XV Suporte .................................................................................................................................................. XVII 1. INTRODUÇÃO .................................................................................................. 1 1.1 Porquê o Node.js?.................................................................................................................................. 1 1.2 Instalação .............................................................................................................................................. 3 1.3 REPL (Read-Eval-Print-Loop) ............................................................................................................... 5 1.4 A primeira aplicação............................................................................................................................ 7 1.5 O primeiro servidor ............................................................................................................................. 8 1.6 Introdução aos módulos ................................................................................................................... 11 1.6.1 Módulos core ............................................................................................................................ 14 1.6.2 Módulos pasta.......................................................................................................................... 14 1.6.3 Pasta especial node_modules .................................................................................................... 16 1.6.4 Objeto module ......................................................................................................................... 16 1.7 Utilitário npm (node package manager) ............................................................................................... 17 1.7.1 Atualização do utilitário npm ................................................................................................. 19 1.7.2 Instalação de pacotes............................................................................................................... 20 1.7.2.1 Instalação global de pacotes ...................................................................................... 25 1.7.3 Atualização de pacotes ........................................................................................................... 26 1.7.4 Desinstalação de pacotes ........................................................................................................ 27 1.7.5 Publicação de pacotes ............................................................................................................. 28 Conclusão .......................................................................................................................................... 29 Bibliografia ........................................................................................................................................ 29 2. EXPRESS ...................................................................................................... 31 2.1 Aplicação............................................................................................................................................. 31 2.2 Criação do projeto inicial .................................................................................................................. 32 2.3 Módulo Express................................................................................................................................... 33 2.3.1 Roteamento .............................................................................................................................. 34 2.3.1.1 String de rota ................................................................................................................ 35 2.3.1.2 Funções de rota ............................................................................................................ 37 2.3.1.3 Método route ............................................................................................................. 38 2.3.1.4 Objeto Router............................................................................................................. 39 2.3.1.5 Definição de várias rotas ............................................................................................ 40 © FCA – Editora de Informática


VIII

NODE.JS – CONSTRUÇÃO DE APLICAÇÕES WEB

2.3.2 Middleware ................................................................................................................................ 41 2.3.3 Motores de templates................................................................................................................ 43 2.3.4 Considerações finais................................................................................................................ 43 2.4 Homepage ............................................................................................................................................. 44 2.4.1 Recuperação inicial dos dados ............................................................................................... 47 Conclusão.................................................................................................................................................. 49 Bibliografia................................................................................................................................................ 49 3. MOTORES DE TEMPLATES .................................................................................. 51 3.1 Introdução ........................................................................................................................................... 51 3.2 Jade ....................................................................................................................................................... 52 3.2.1 Atributos ................................................................................................................................... 54 3.2.2 Elementos ................................................................................................................................. 56 3.2.3 Texto .......................................................................................................................................... 56 3.2.4 Código ....................................................................................................................................... 57 3.2.4.1 Condições ..................................................................................................................... 57 3.2.4.2 Iterações ........................................................................................................................ 58 3.2.5 Interpolação de strings ............................................................................................................ 58 3.2.5.1 Interpolação de tags .................................................................................................... 59 3.2.6 Mixins ........................................................................................................................................ 59 3.2.7 Heranças de templates .............................................................................................................. 60 3.2.7.1 Definição da personalização ...................................................................................... 61 3.2.7.2 Importação de templates .............................................................................................. 62 3.3 Vash ...................................................................................................................................................... 62 3.4 Vista de contactos .............................................................................................................................. 67 3.4.1 Acesso a recursos estáticos ..................................................................................................... 69 Conclusão.................................................................................................................................................. 71 Bibliografia................................................................................................................................................ 71 4. UTILITÁRIOS ................................................................................................. 73 4.1 Utilização de livrarias cliente ........................................................................................................... 73 4.2 Bower .................................................................................................................................................... 73 4.2.1 Outras opções disponíveis ..................................................................................................... 76 4.2.2 Configuração ............................................................................................................................ 76 4.3 Aplicação contactos: adição do Bootstrap.......................................................................................... 77 4.4 Grunt .................................................................................................................................................... 79 4.5 Utilização do Bootstrap ...................................................................................................................... 85 Conclusão.................................................................................................................................................. 87 Bibliografia................................................................................................................................................ 87 5. BASES DE DADOS ........................................................................................... 89 5.1 Base de dados relacional vs. NoSQL ................................................................................................ 89 5.2 SQL Server ........................................................................................................................................... 90 5.2.1 Utilização de promises.............................................................................................................. 94 5.3 MongoDB ............................................................................................................................................. 96 5.4 Aplicação contactos: inicialização da base de dados ................................................................... 104 © FCA – Editora de Informática


ÍNDICE GERAL

IX

5.5 Aplicação contactos: adição de nova entrada............................................................................... 107 5.5.1 Middleware body-parser ........................................................................................................... 109 5.5.2 Middleware connect-flash ........................................................................................................ 110 Conclusão................................................................................................................................................ 113 Bibliografia.............................................................................................................................................. 113 6. APLICAÇÕES SPA ......................................................................................... 115 6.1 Introdução ......................................................................................................................................... 115 6.2 Criação de uma API HTTP ............................................................................................................. 115 6.2.1 Carregamento de contacto.................................................................................................... 117 6.2.2 Adição de novos contactos ................................................................................................... 120 6.2.3 Eliminação de contactos existentes ..................................................................................... 122 6.3 Consumo da API HTTP .................................................................................................................. 124 6.3.1 Criação do controlador AngularJS ....................................................................................... 125 6.3.2 Criação de rota para apresentação da página .................................................................... 131 6.3.3 Alteração da regra de criação do ficheiro de script ........................................................... 131 6.3.4 Definição da página HTML de contactos ........................................................................... 132 6.3.5 Detalhes finais ........................................................................................................................ 135 6.4 Melhorias possíveis ......................................................................................................................... 135 Conclusão................................................................................................................................................ 136 Bibliografia.............................................................................................................................................. 136 7. AUTENTICAÇÃO ............................................................................................ 137 7.1 Introdução ......................................................................................................................................... 137 7.2 Autenticação, autorização e módulo Passport .............................................................................. 137 7.3 Gestão de utilizadores ..................................................................................................................... 139 7.4 Operações relacionadas com palavras-chave ............................................................................... 141 7.5 Registo de utilizadores .................................................................................................................... 144 7.6 Utilização de Passport ...................................................................................................................... 148 7.6.1 Configuração da estratégia local ......................................................................................... 151 7.6.2 Criação da página de login ................................................................................................... 154 7.6.3 Alteração do menu ................................................................................................................ 157 7.6.4 Final de sessão autenticada .................................................................................................. 158 7.6.5 Autorização de rotas ............................................................................................................. 159 Conclusão................................................................................................................................................ 162 Bibliografia.............................................................................................................................................. 162 8. CONSIDERAÇÕES FINAIS ................................................................................ 163 8.1 Introdução ......................................................................................................................................... 163 8.2 Timers ................................................................................................................................................. 163 8.3 Eventos .............................................................................................................................................. 164 8.4 HTTP ................................................................................................................................................. 167 8.4.1 Servidores ............................................................................................................................... 168 8.4.1.1 Objeto ServerRequest .......................................................................................... 169 8.4.1.2 Objeto ServerResponse........................................................................................ 170 8.4.2 Clientes ................................................................................................................................... 171 © FCA – Editora de Informática


X

NODE.JS – CONSTRUÇÃO DE APLICAÇÕES WEB

8.4.2.1 Upload de dados ......................................................................................................... 172 8.5 URL .................................................................................................................................................... 173 8.6 Query string ....................................................................................................................................... 174 8.7 Streams ............................................................................................................................................... 176 8.8 File System (fs) ................................................................................................................................ 178 8.9 Buffer .................................................................................................................................................. 180 8.10 Crypto ............................................................................................................................................... 183 8.10.1 Hashing .................................................................................................................................. 183 8.10.2 HMAC ................................................................................................................................... 184 8.11 Process .............................................................................................................................................. 185 8.12 Web Sockets ...................................................................................................................................... 188 Conclusão................................................................................................................................................ 192 Bibliografia.............................................................................................................................................. 192 ÍNDICE REMISSIVO ........................................................................................... 193

© FCA – Editora de Informática


AGRADECIMENTOS Em primeiro lugar, quero agradecer à minha esposa, Marina, pelo apoio fornecido durante todo o processo de escrita do livro. Não posso deixar de referir a participação do Helder Robinson: as suas revisões, contribuições técnicas e opinião sincera tiveram uma influência positiva no resultado final. Finalmente, queria também agradecer à Ana Correia e à Laura Faia, da FCA, pela disponibilidade demonstrada ao longo do projeto.

Luís Abreu

© FCA – Editora de Informática



SOBRE O LIVRO Nos últimos anos, o Node.js (ou simplesmente Node, como é conhecido por muitos dos seus fãs) tem ganhado cada vez mais popularidade e peso na comunidade de programação. Esta plataforma dirigida por eventos I/O (Input/Output) recorre ao motor de JavaScript V8 para permitir a escrita de aplicações em JavaScript. Os princípios sobre os quais assenta (acessos I/O assíncronos, suporte predefinido para os protocolos mais importantes e utilização de streams) foram fundamentais para garantir a sua crescente utilização no desenvolvimento de aplicações e utilitários.

O QUE POSSO ENCONTRAR NESTE LIVRO? Neste livro, são apresentadas as principais caraterísticas e funcionalidades disponibilizadas pela plataforma Node.js. Para além da apresentação dessas caraterísticas base mais importantes, introduzimos ainda alguns dos pacotes Node.js que disponibilizam os módulos e ferramentas mais usados na construção de aplicações Web nesta plataforma. Ao longo dos capítulos seguintes, estes módulos são utilizados na criação de uma aplicação Web simples, cujo principal objetivo é ilustrar a aplicação prática de todos os princípios apresentados ao longo do livro. Assim, no final deste livro, o leitor terá à sua disposição uma aplicação Web que recorre a uma base de dados NoSQL para efetuar o armazenamento da informação necessária ao seu funcionamento. A aplicação mostra ainda como podemos gerar páginas tradicionais através de uma arquitetura MVC, onde um controlador é responsável por obter os dados que são renderizados por um motor de vistas. Finalmente, temos ainda código que ilustra a criação de serviços de dados que são consumidos por código cliente (por outras palavras, ilustramos ainda uma possível forma de criarmos SPA – Single Page Applications – a partir desta plataforma).

REQUISITOS Apesar de ser um livro prático, a verdade é que ele foi escrito para permitir que a aprendizagem das funcionalidades da plataforma possa ser feita sem que o leitor tenha de estar sentado em frente de um computador. Todos os exemplos apresentados no livro podem ser obtidos a partir do site da editora (http://www.fca.pt). A criação de aplicações para Node.js obriga-nos apenas a instalar a plataforma (download gratuito a partir de https://nodejs.org/en/download/). A instalação da plataforma © FCA – Editora de Informática


XIV

NODE.JS – CONSTRUÇÃO DE APLICAÇÕES WEB

introduz também o gestor de pacotes do Node.js, que, como veremos, é usado para instalarmos os pacotes com os módulos que serão utilizados ao longo do livro. Para além disso, a instalação encarrega-se ainda de efetuar todas as alterações necessárias à configuração do sistema para garantir a utilização dos comandos necessários a partir de qualquer pasta do sistema. Apesar de ser possível recorrermos a um editor de texto para escrever o código usado nos exemplos que acompanham este livro, a verdade é que a produtividade será maior se utilizarmos um dos vários IDE (Integrated Development Environments) existentes. O leitor proveniente do mundo .NET pode, por exemplo, recorrer ao Node.js Tools for Visual Studio (pode ser obtido a partir de https://www.visualstudio.com/features/node-jsvs.aspx e utilizado em conjunto com a versão Community do Visual Studio – esta versão é gratuita e pode ser obtida a partir de https://www.visualstudio.com/post-downloadvs?sku=community&clcid=0x409). Neste livro, optámos por criar os exemplos através do editor WebStorm da Jetbrains. Este editor não é gratuito, mas disponibiliza uma versão para testes que pode ser utilizada durante 30 dias (https://www.jetbrains.com/webstorm). Apesar de representar um investimento, este é um bom editor para quem necessita de escrever código JavaScript no dia a dia. Note-se ainda que este editor não está limitado apenas à escrita de código Node.js, podendo mesmo ser usado na escrita de código usado no lado cliente (por exemplo, JQuery, AngularJS, CSS). Para além da plataforma Node.js, o leitor que queira testar o código do livro necessita ainda de instalar outras aplicações. Por exemplo, no Capítulo 5, apresentamos código que mostra como podemos interagir com bases de dados relacionais e base de dados NoSQL a partir de aplicações Node.js. Sempre que seja preciso instalar aplicações ou componentes extra, o leitor poderá obter todas as informações necessárias à instalação no capítulo onde essa aplicação é utilizada.

A QUEM SE DIRIGE ESTE LIVRO? Este livro é dirigido a todos aqueles que pretendem colocar-se rapidamente a par das principais funcionalidades introduzidas pela plataforma Node.js e pelos principais módulos utilizados na construção de aplicações Web. O livro parte do pressuposto de que o leitor já tem alguns conhecimentos e experiência na escrita de código JavaScript, pelo que não são apresentadas quaisquer noções básicas ou de introdução à linguagem. Se o leitor está interessado em aprender JavaScript ou estar ao corrente das novidades introduzidas pelo JavaScript 6, então recomendados a leitura dos livros JavaScript e JavaScript 6, ambos publicados pela FCA.

© FCA – Editora de Informática


SOBRE O LIVRO

XV

CONVENÇÕES Ao longo deste livro, optou-se por seguir um conjunto de convenções que facilitam a interpretação do texto e do código apresentados. Assim, todos os excertos de código são apresentados no formato seguinte: let a = 10;

Por sua vez, as notas ou observações importantes poderão ser encontradas no interior de uma secção semelhante à seguinte: Nota importante Esta é uma nota ou observação importante.

ORGANIZAÇÃO DO LIVRO Este livro encontra-se dividido em oito capítulos, que podem ser lidos sequencialmente ou, se o leitor assim o preferir, alternadamente (isto é, sem respeitar a ordem de capítulos apresentada). A leitura sequencial do livro conduz o leitor ao longo do processo de construção da aplicação Web que acompanha este livro. Por outro lado, a leitura não sequencial dos capítulos permite o uso do livro como referência para funcionalidades. Esta aproximação é possível devido ao facto de todas as (poucas) dependências entre capítulos estarem devidamente identificadas.

CAPÍTULO 1: INTRODUÇÃO Este capítulo inicia o nosso estudo da plataforma Node.js. Depois de justificar o por quê do uso desta plataforma, o capítulo documenta a sua instalação e efetua uma introdução rápida ao seu ambiente de runtime. O capítulo apresenta ainda o conceito de módulo e mostra como podemos utilizar os pacotes publicados no registo central através do uso do gestor de pacotes do Node.js (NPM).

CAPÍTULO 2: EXPRESS Neste capítulo, começamos por definir os principais objetivos da aplicação que acompanha este livro para, em seguida, apresentarmos detalhadamente o módulo Express. Com a utilização deste módulo, passamos a poder definir rotas e componentes de middleware, duas abstrações que serão muito importantes na simplificação do código e que nos permitem utilizar uma aproximação baseada na arquitetura MVC (Model-View-Controller) na aplicação Web que acompanha o livro. © FCA – Editora de Informática


XVI

NODE.JS – CONSTRUÇÃO DE APLICAÇÕES WEB

CAPÍTULO 3: MOTORES DE TEMPLATES Neste capítulo, introduzimos o conceito de motores de templates e apresentamos as principais caraterísticas associadas à utilização de dois dos motores de templates mais utilizados quando optamos pelo uso da biblioteca Express: estamos a falar dos motores Jade e Vash. Depois de apresentar as principais caraterísticas de cada um desses motores, o capítulo recorre ao motor Jade para criar a primeira vista utilizada pela aplicação que acompanha o livro.

CAPÍTULO 4: UTILITÁRIOS Neste capítulo, apresentamos os utilitários Bower e Grunt. O Bower desempenha um papel semelhante ao NPM, mas concentra-se na gestão de pacotes de bibliotecas cliente. Por sua vez, com o Grunt podemos recorrer a JavaScript para efetuar a automatização de tarefas. Como veremos, a combinação destas duas ferramentas permitir-nos-á melhorar o aspeto da nossa aplicação através da adição do Bootstrap (com o Bower adicionamos referências às livrarias cliente e usamos o Grunt para automatizar as tarefas de publicação dos componentes necessários).

CAPÍTULO 5: BASES DE DADOS A utilização de bases de dados é uma necessidade comum a praticamente todas as aplicações Web. Neste capítulo, começamos por efetuar uma pequena comparação entre bases de dados relacionais e bases de dados NoSQL. Em seguida, apresentamos exemplos da interação com base de dados de ambos os tipos. O capítulo encerra com a apresentação de várias alterações efetuadas na aplicação que acompanha o livro e que permitem guardar os dados usados pela aplicação numa base de dados MongoDB.

CAPÍTULO 6: SPA Nos dias que correm, é cada vez mais usual termos aplicações Web ricas, que recorrem ao servidor apenas para obterem os dados necessários ao seu funcionamento. Estas aplicações são conhecidas como SPA (Single-Page Applications) e são o foco deste capítulo. Como veremos, a criação de serviços que se limitam a devolver dados em formato JSON (JavaScript Object Notation) é muito simples em Node.js. O consumo destes dados a partir do cliente não depende da plataforma em si, mas esta ajuda-nos a gerir corretamente as dependências para as livrarias cliente necessárias.

© FCA – Editora de Informática


SOBRE O LIVRO XVII

CAPÍTULO 7: AUTENTICAÇÃO A autenticação e autorização são dois conceitos transversais à maior parte das aplicações Web. Depois de introduzirmos ambos os conceitos, apresentamos algumas das funcionalidades disponibilizadas pelo módulo Passport. Este módulo é compatível com a pipeline introduzida pela biblioteca Express e permite-nos autenticar um utilizador de acordo com uma de várias estratégias predefinidas. Neste capítulo, ilustramos o código necessário à autenticação baseada no armazenamento local de credenciais e apresentamos o código necessário à verificação de autorização na consulta e modificação dos contactos geridos pela aplicação.

CAPÍTULO 8: CONSIDERAÇÕES FINAIS Neste capítulo, apresentamos algumas das principais caraterísticas dos módulos core introduzidos automaticamente pelo Node.js. Eventos, tratamentos de pedidos HTTP, utilização de streams ou criptografia são tópicos abordados ao longo deste capítulo. O capítulo encerra com a apresentação do módulo Socket.io. Apesar de este módulo não fazer parte dos módulos predefinidos expostos pela plataforma, a realidade é que o seu uso permite-nos o estabelecimento de um canal de comunicação bidirecional em tempo real entre cliente e servidor numa aplicação Web (esta é uma funcionalidade que, com toda a certeza, será cada vez mais utilizada nas aplicações Web).

SUPORTE Este livro foi feito com base na versão 5.0.0 da plataforma Node.js. Se, por acaso, o leitor encontrar informação que lhe pareça incorreta, ou tiver sugestões em relação ao conteúdo de alguma secção do livro, então não hesite e envie um email com as suas questões para labreu@gmail.com. Eventuais alterações e uma errata serão publicadas no site da editora em http://www.fca.pt.

© FCA – Editora de Informática



1

INTRODUÇÃO

1

De acordo com o site (https://nodejs.org/en), o Node.js é um ambiente de runtime de JavaScript baseado no motor de JavaScript V8 (este é o motor de JavaScript usado pelo browser Chrome). Do ponto de vista arquitetural, o Node.js carateriza-se por utilizar um modelo direcionado a eventos, onde as operações de I/O são efetuadas de forma assíncrona para evitar bloqueios desnecessários. Atualmente, o seu ecossistema de pacotes disponibiliza o maior número de bibliotecas open source existentes no mundo, que podem ser utilizadas em qualquer aplicação através do uso do utilitário npm (Node.js Package Manager).

1.1

PORQUÊ O NODE.JS?

O Node.js significa coisas diferentes para pessoas diferentes. Contudo, a maioria das pessoas concorda com o facto de podermos classificá-lo como uma plataforma que permite a execução de JavaScript fora do browser. Como referimos, o Node.js recorre ao motor de runtime JavaScript V8, motor este que é usado internamente pelo browser Chrome (desenvolvido pela Google). O Node.js não se limita apenas a utilizar este excelente motor de runtime, que recorre algumas das técnicas mais avançadas existentes na área dos compiladores. Em vez disso, a plataforma aproveitou ainda para efetuar algumas otimizações que são muito úteis quando pensamos na execução de JavaScript fora do browser. Por exemplo, a manipulação de dados binários é uma das operações que beneficiou desta interação entre a plataforma e o motor V8 (foi a pensar neste tipo de operações que o Node.js introduziu a classe Buffer, que é apresentada no Capítulo 8). Internamente, a arquitetura do Node.js recorre ao chamado ciclo de eventos (event loop) para permitir a fácil criação de aplicações seguras e escaláveis. Como é óbvio, cada arquitetura tem vantagens e desvantagens. No caso desta plataforma, os seus criadores optaram por uma arquitetura que reduz a complexidade inerente à criação de aplicações, sem que isso implique uma penalização ao nível da sua performance. Esta aproximação baseada no uso de um ciclo de eventos é suportada por um conjunto de bibliotecas que permitem a realização de operações de I/O de forma assíncrona. Por outras palavras, o acesso a um ficheiro ou a execução de uma consulta sobre uma base de dados não resulta num bloqueio do sistema. Em vez disso, o Node.js prefere notificar a aplicação quando esses dados estiverem disponíveis através da geração de um evento. Este comportamento predefinido contrasta com o disponibilizado por outras plataformas mais maduras, como, © FCA – Editora de Informática


2

NODE.JS – CONSTRUÇÃO DE APLICAÇÕES WEB

por exemplo, o ASP.NET MVC (a realização de operações assíncronas é suportada, mas não é a abordagem predefinida). O ciclo de eventos em Node.js O Node.js recorre a um ciclo de eventos (event loop) para sinalizar a ocorrência de determinados acontecimentos importantes. O leitor com experiência na escrita de código JavaScript usado em páginas HTML notará algumas semelhanças entre este modelo e o usado pelos browsers. Por exemplo, suponhamos que temos uma página HTML com um botão cujo evento click foi associado a uma determinada função. Um clique sobre um botão resulta na adição de um evento à pilha de eventos controlada pelo tab do browser que apresenta a página. Este evento acaba por conduzir à execução da função que tinha sido previamente associada ao evento click desse botão. Estes princípios são reutilizados pelo Node.js no tratamento de operações I/O. Todos os acontecimentos importantes resultam na geração de um evento em Node.js. Por exemplo, a leitura de um ficheiro é, por predefinição, uma operação assíncrona. Quando iniciamos um processo de leitura, temos sempre de fornecer uma função de callback que será responsável por interpretar o conteúdo desse ficheiro. Esta função de callback será apenas invocada quando o Node.js gerar um evento que sinaliza o final do carregamento dos conteúdos desse ficheiro. Na prática, podemos ver o ciclo de eventos como sendo uma fila do tipo FIFO (First in, first out), em que cada elemento contém uma sequência de instruções (tipicamente definidas no interior de uma função) que devem ser executadas pela aplicação. Sempre que ocorre um novo evento, é adicionada uma nova entrada ao final dessa fila. A próxima operação a executar pela aplicação é sempre a operação que está no início dessa fila. Nesta altura, importa reter que todo o código JavaScript escrito para Node.js é executado numa única thread, pelo que é fácil concluirmos que devemos ter algum cuidado no código colocado no interior das funções que tratam os eventos gerados pela plataforma. Se estivermos perante cálculos intensivos no interior de uma função desse tipo (isto é, se estivermos perante código que necessita de vários ciclos de CPU (Central Processing Unit) para realizar uma determinada operação), então um servidor Node.js será incapaz de tratar mais pedidos enquanto esses cálculos estiverem a ser efetuados. Este comportamento predefinido do Node.js foi muito criticado por várias pessoas. Contudo, a alternativa que é seguida por muitas outras plataformas também introduz vários problemas. Por exemplo, a utilização de várias threads pode contribuir para aumentar o throughput de uma aplicação, mas também implica a necessidade de utilização de mecanismos adicionais de coordenação. Estes mecanismos nem sempre são lineares e, como já foi comprovado várias vezes no passado, contribuem muitas vezes para degradar a performance de uma aplicação. Portanto, o Node.js optou por uma aproximação pragmática baseada no uso de uma única thread, em que toda a interação com I/O é feita assincronamente, sendo a conclusão das operações sinalizada através da geração de eventos que, por sua vez, também são adicionados ao final da fila de eventos. Esta aposta na realização de operações assíncronas é boa, uma vez que estamos perante operações que demoram algum tempo a concluir e não dependem diretamente do processador. Nesta altura, o leitor poderá estar a interrogar-se acerca de como deverá proceder quando estiver perante cenários de computação intensiva. Nesses casos, os cálculos devem ser efetuados noutra thread através do uso de Web Workers – o leitor interessado pode obter mais informações no livro

© FCA – Editora de Informática


INTRODUÇÃO

3

JavaScript, também publicado pela FCA (http://www.fca.pt/pt/catalogo/informatica/tecnologiasprogramacao-web/javascript/). Importa ainda salientar que todas as observações efetuadas nesta nota são feitas a partir do ângulo do programador Node.js. Como é óbvio, os detalhes de implementação (que se encontram totalmente abstraídos no core da plataforma) até podem recorrer a várias threads para garantirem a realização assíncrona das operações I/O, mas a verdade é que esses detalhes nunca transpiram para o programador que está a criar uma aplicação Node.js. Um programador Node.js sabe apenas que todo o código é executado numa única thread e que essa thread não deve referenciar funções com cálculos intensivos.

Nos dias que correm, em que a explosão da Web fez com que o JavaScript se tornasse na linguagem da moda e as aplicações são cada vez mais complexas, a possibilidade de reutilização dos conceitos, recomendações e código entre lado cliente e servidor é uma mais-valia a que os programadores não ficarão, com toda a certeza, alheios. E esta é mais uma área onde o Node.js brilha. Se é verdade que existem outras opções para a escrita de JavaScript no lado servidor, também é verdade que nenhuma dessas plataformas possui caraterísticas semelhantes às disponibilizadas pelo Node.js: para além da facilidade que carateriza a escrita de aplicações em Node.js, dificilmente encontraremos outra plataforma que disponibilize uma tão grande variedade de módulos e plugins que podem ser consumidos gratuitamente por parte das nossas aplicações.

1.2

INSTALAÇÃO

Atualmente, o Node.js corre em Windows, Linux, Mac e outros sistemas POSIX (Portable Operating System Interface – por exemplo, Solaris ou BSD). A forma mais fácil de o instalar passa por efetuarmos o download do pacote adequado a partir do site https://nodejs.org/en/download/ (Figura 1.1).

FIGURA 1.1 – Obtenção do pacote de instalação a partir do site do Node.js © FCA – Editora de Informática


4

NODE.JS – CONSTRUÇÃO DE APLICAÇÕES WEB

Alternativamente, o leitor interessado pode obter todo o código fonte do projeto a partir do repositório existente em https://github.com/nodejs/node. Neste caso, o leitor terá acesso a todas as funcionalidades disponibilizadas pela versão mais recente da plataforma (algumas delas poderão estar ainda sujeitas a bugs), mas também será responsável pela compilação do projeto (o que pode não ser uma tarefa muito simples). Neste caso, e uma vez que a máquina usada na escrita do livro recorre ao sistema operativo Windows da Microsoft, vamos utilizar o instalador para Windows. Depois de darmos início ao processo de instalação e de aceitarmos a licença proposta, temos de indicar a pasta onde queremos instalar o Node.js (Figura 1.2).

FIGURA 1.2 – Definição da pasta onde o Node.js é instalado

Em seguida, temos acesso a uma janela que nos permite escolher os componentes que devem ser instalados. Por predefinição, e como é possível verificar através da Figura 1.3, o instalador procede à execução de todas as opções disponíveis (neste caso, vamos aceitar estas escolhas e clicar no botão Next).

FIGURA 1.3 – Opções disponibilizadas pelo instalador do Node.js © FCA – Editora de Informática


2

EXPRESS

1

No Capítulo 1, criámos o nosso primeiro servidor Web em Node.js. Neste capítulo, veremos como podemos recorrer ao módulo Express para criar uma aplicação Web compatível com a arquitetura MVC (Model-View-Controller). Como veremos em seguida, este módulo introduz algumas funcionalidades importantes, como o roteamento (routing) ou o suporte a motores de templates, que são fundamentais para o programador que necessita de criar aplicações Web.

2.1

APLICAÇÃO

Antes de analisarmos o módulo Express, vamos efetuar um pequeno desvio para apresentar a aplicação que vamos criar ao longo dos próximos capítulos. O principal objetivo desta aplicação é permitir a fácil gestão dos contactos de várias pessoas. Optámos por identificar cada pessoa pelo seu nome, sendo que cada uma pode possuir vários contactos, que serão representados apenas por strings. Como é óbvio, este tipo de caraterização está muito longe do que seria necessário no mundo real, mas é mais do que o suficiente para o nosso objetivo (que, recorde-se, passa por apresentar o Node.js e alguns dos principais módulos usados na construção de aplicações Web). O excerto seguinte recorre à sintaxe literal para ilustrar o aspeto da nossa agenda de contactos que será usada ao longo deste livro: let contactos = [ { nome: "Luis", contactos: [ "123456789", "teste@gmail.com"] }, { nome: "Júlia", contactos: [ "999999999"] }, { nome: "Maria", contactos: ["maria@gmail.com"] } ];

Do ponto de vista da aplicação propriamente dita, a ideia passa por criarmos uma página de entrada que apresenta todos os nomes dos contactos previamente armazenados. A partir desta página, podemos adicionar novas entradas na agenda ou navegar para outra página que permita a adição ou a eliminação de contactos de uma pessoa que foi previamente armazenada na agenda. Agora que já temos um objetivo definido, está na hora de avançarmos com a construção da nossa aplicação Web. © FCA – Editora de Informática


32

2.2

NODE.JS – CONSTRUÇÃO DE APLICAÇÕES WEB

CRIAÇÃO DO PROJETO INICIAL

A primeira coisa a fazer é criarmos uma pasta que será usada no alojamento da nossa aplicação. Neste caso, vamos criar uma nova pasta designada por contactos. No interior dessa pasta, vamos começar por criar dois ficheiros: package.json e index.js. Como vimos no Capítulo 1, a criação do pacote package.json pode ser feita através do comando npm init. Neste caso, optámos por criar o ficheiro com os valores indicados na Figura 2.1.

FIGURA 2.1 – Criação do ficheiro package.json

No ficheiro index.js, vamos começar por criar um servidor que se limita a replicar o URL (Uniform Resource Locator) do pedido efetuado para a consola. Como vimos no Capítulo 1, este comportamento obriga-nos a requerer a importação do módulo core http através do método require. O excerto seguinte apresenta o código inicial definido no ficheiro index.js: "use strict"; let http = require("http"); let servidor = http.createServer((req, res) => { console.log(req.url); res.end("hi"); }); servidor.listen(9001);

Até aqui, nada de novo. No interior do ficheiro, criamos um servidor que recebe pedidos na porta 9001 e que responde a todos com o texto "hi". A Figura 2.2 ilustra o que acontece depois de iniciarmos a aplicação (node index.js) e de navegarmos para alguns URL diferentes.

© FCA – Editora de Informática


EXPRESS

33

FIGURA 2.2 – Testes de URL na aplicação inicial

A instrução console.log permite-nos analisar os URL pedidos durante o nosso pequeno teste. Como é possível verificar, podemos recorrer à propriedade req.url a partir da função de callback para obter o URL pedido pelo cliente atual. Em teoria, a existência desta propriedade permitir-nos-ia tratar todos os pedidos efetuados a partir de uma única função. Contudo, esta aproximação seria problemática e não seria nada prática. Basta pensarmos no trabalho associado ao parsing do URL para esquecermos rapidamente esta ideia. Felizmente para nós, existem módulos que solucionam este tipo de problemas e podem ser reutilizados nas nossas aplicações. Um desses módulos é o módulo Express, aquele que é, com toda a certeza, a plataforma Web mais usada em aplicações Web Node.js.

2.3

MÓDULO EXPRESS

O site oficial do módulo (http://expressjs.com/) define-o como uma plataforma Web minimalista e flexível, que simplifica a criação de aplicações Web em Node.js. O roteamento de pedidos e a possibilidade de criação de middleware são duas das funcionalidades mais importantes disponibilizadas por esta plataforma. Como seria de esperar, a instalação do módulo é feita através do uso do utilitário npm: npm install express --save

Depois de instalarmos o módulo, temos de efetuar algumas alterações no código fonte existente no ficheiro index.js: "use strict"; let express = require("express"); let app = express(); © FCA – Editora de Informática


34

NODE.JS – CONSTRUÇÃO DE APLICAÇÕES WEB

app.listen(9001);

A importação do módulo Express devolve uma função (único objeto que é exportado pelo módulo) que é atribuída à variável local express. Ao ser executada, esta função devolve um objeto do tipo Application que representa programaticamente uma aplicação Express. Este objeto desempenha vários papéis importantes numa aplicação Express. Por exemplo, é através dele que definimos rotas ou efetuamos a configuração de middleware usado pela aplicação. No exemplo anterior, este objeto é guardado na variável app. A introdução deste módulo permite-nos ainda omitir a criação explícita de um objeto Server, já que o objeto Application referenciado por app é capaz de fazê-lo internamente a partir da invocação do método listen. Na prática, isto significa que o código anterior é equivalente ao seguinte: "use strict"; let http = require("http"); let express = require("express"); let app = express(); http.createServer(app).listen(9001);

Nesta altura, e como não temos nenhuma rota definida, qualquer navegação até ao nosso site resulta numa resposta semelhante à apresentada na Figura 2.3.

FIGURA 2.3 – Falta de roteamento provoca mensagem de erro

A resolução deste problema passa pela definição de uma ou mais rotas que serão usadas na satisfação dos pedidos HTTP efetuados.

2.3.1

ROTEAMENTO

É através do roteamento que podemos associar uma ou mais funções a um URL. Por outras palavras, o roteamento permite-nos indicar uma ou mais funções que serão responsáveis por definir a resposta devolvida a um pedido HTTP efetuado sobre um determinado URL. Uma rota é sempre definida à custa da combinação de uma string de © FCA – Editora de Informática


3

MOTORES DE TEMPLATES

1

No Capítulo 2, vimos como recorrer ao módulo Express para criarmos uma aplicação Web baseada na arquitetura MVC (Model-View-Controller). Neste capítulo, concentramo-nos na definição e criação de vistas através da apresentação de dois dos motores de templates mais usados (Jade e Vash). O capítulo encerra com a criação de vistas Jade para a aplicação de gestão de contactos.

3.1

INTRODUÇÃO Como o leitor deve estar recordado, encerrámos o Capítulo 2 com o controlador

ControladorHome a gerar diretamente HTML a partir do interior do seu método index.

Como é óbvio, esta é uma má aproximação, porque – como mencionámos – contribui para dificultar a legibilidade e a manutenção do código. Portanto, não deverá ser surpresa quando afirmamos que esta aproximação é considerada uma má prática que deve ser evitada a todo o custo. Foi a pensar nisto que a livraria Express introduziu o conceito de motor de templates para descrever os componentes que se concentram apenas na apresentação de dados ao utilizador. Tipicamente, estes motores costumam ser utilizados na geração do HTML enviado como resposta a um pedido HTTP efetuado por um cliente. A livraria Express segue, uma vez mais, uma aproximação minimalista no que diz respeito aos motores de templates. Em vez de disponibilizar um motor predefinido, a livraria concentra-se em definir o protocolo de comunicação genérico usado na comunicação com os motores de templates (a construção de motores de templates é um tópico avançado que não será apresentado neste livro; o leitor interessado poderá obter mais detalhes em http://expressjs.com/en/advanced/developing-template-engines.html). Na prática, a utilização de um motor de templates pressupõe a instalação de um pacote npm que, por sua vez, se encarrega de instalar todos os módulos necessários ao seu correto funcionamento. Em seguida, e como mencionámos no Capítulo 2, temos de efetuar o seu registo na aplicação Express e indicar a pasta onde serão colocados os templates usados pelo motor. O exemplo seguinte mostra como podemos registar o motor de templates Jade e definir a pasta que contém as vistas usadas por uma aplicação Express: app.set( "views", "/views"); © FCA – Editora de Informática


52

NODE.JS – CONSTRUÇÃO DE APLICAÇÕES WEB

app.set("view engine", "Jade");

Depois de termos, pelo menos, um motor de templates registado, podemos renderizar um template a partir do interior de uma função de rota através do método render, conforme ilustrado em seguida: res.render("index", { nome: "Luis"} );

Neste caso, a resposta devolvida ao cliente será obtida a partir do parsing do ficheiro index.Jade situado no interior da pasta views. Note-se ainda como passámos um objeto que poderá ser utilizado pelo motor de templates para injetar informação na vista gerada. Agora que já temos algumas noções básicas sobre o seu uso, está na hora de apresentarmos alguns dos motores de templates existentes.

3.2

JADE

Nos tempos que correm, o Jade é, muito provavelmente, o motor de templates mais usado na construção de aplicações Web em Node.js. Como veremos em seguida, uma das principais justificações para a sua fama reside no facto de a sintaxe usada na construção de vistas ser muito concisa. Este será o motor utilizado para gerar os templates usados na aplicação de contactos que acompanha este livro, pelo que optámos por efetuar uma abordagem aprofundada das principais funcionalidades disponibilizadas por este motor. O uso deste motor de templates numa aplicação Web só é possível depois de instalarmos o pacote Jade: npm install Jade --save

Para ilustrar algumas das funcionalidades disponibilizadas por este motor, vamos começar por criar uma aplicação Node.js muito simples (cap03/jade/index.js): "use strict"; let express = require("express"); let app = express(); app.set("view engine", "Jade"); app.get("/", (req, res ) => res.render( "index", { nome: "Luis", titulo: "Olá, mundo" } ) ); app.listen(9001);

Depois de registarmos o motor de templates Jade, podemos invocar o método render para que a resposta a todos os pedidos efetuados sobre o URL / seja obtida a partir do parsing da vista index. O leitor atento reparou, com toda a certeza, no facto de não termos recorrido ao método require para importar o motor de templates. Esta importação explícita não é © FCA – Editora de Informática


MOTORES DE TEMPLATES

53

necessária, já que acaba por ser efetuada indiretamente aquando da definição do motor de templates (efetuada previamente através do método set). Outro aspeto que poderá estar a incomodar o leitor é a omissão da pasta onde são guardados os templates usados pelo motor de templates Jade (variável global Express views apresentada na secção 3.1). Essa indicação só é necessária se quisermos colocar os templates numa pasta diferente da usada por predefinição (por omissão, o motor procura as vistas no interior da pasta views). Outro aspeto a reter reside no facto de as vistas processadas por este motor deverem ser guardadas em ficheiros com extensão .jade. Quando isso acontece, não é necessário indicar a extensão do ficheiro aquando da invocação do método res.render. Analisemos, então, o código mantido no interior do template index.jade (cap03/ /jade/views/index.jade): //-index.Jade doctype html html(lang="pt") head title=titulo body h1 Ola, #{nome}

Como referimos, a principal caraterística associada ao uso deste motor é a forma concisa usada na escrita do HTML. Em vez de recorrer às tags HTML para definir a estrutura de uma página, o motor de templates Jade recorre à indentação para definir a posição de cada elemento na hierarquia da página. Ao olharmos para o excerto anterior, é fácil concluir que esta estratégia contribui para reduzir o código final escrito, sem que isso implique uma diminuição da sua legibilidade. Comentários em Jade Os comentários são identificados pelos carateres //ou //-. No primeiro caso, o comentário é transformado num comentário HTML que é injetado na página. Por sua vez, o segundo tipo de comentário fica apenas no código usado no template. O excerto seguinte ilustra ambas as opções: //comentario simples na pagina //-comentario simples codigo apenas p teste Em seguida, apresentamos o HTML gerado a partir do parsing do código anterior: <!--comentario --> p teste

© FCA – Editora de Informática


54

NODE.JS – CONSTRUÇÃO DE APLICAÇÕES WEB

A primeira linha definida no template anterior identifica o tipo de conteúdo como sendo HTML5. Para além do valor html, existem outros valores que podem ser utilizados para obtermos outros doctype conhecidos (mais detalhes podem ser consultados na documentação existente em http://Jade-lang.com/reference/doctype/). Por exemplo, a instrução doctype xml é convertida na seguinte markup: <?xml version="1.0" encoding="utf-8" ?>

Na segunda linha, introduzimos o elemento de topo html e definimos o valor do atributo lang (os atributos podem ser definidos no interior de parêntesis). O título da página é alimentado a partir do objeto que foi passado ao método render (note-se como a atribuição do valor proveniente de uma propriedade do modelo passado à vista a um elemento é feita através da sintaxe =propriedade). O template anterior mostra ainda como podemos misturar texto com valores provenientes de uma propriedade do objeto passado ao método render (atribuição do valor definido no interior do elemento h1). Nestes cenários, temos de recorrer à sintaxe especial baseada na interpolação de strings identificada pelo uso dos carateres #{}. A Figura 3.1 ilustra o resultado obtido quando navegamos para esta página.

FIGURA 3.1 – Primeira utilização do motor Jade

3.2.1

ATRIBUTOS

Como vimos no exemplo anterior, a definição de atributos pode ser efetuada através de expressões delimitadas por parêntesis. Para além de valores constantes, podemos ainda obter um atributo a partir do uso de expressões JavaScript, conforme é possível verificar através do excerto seguinte: doctype html html(lang="pt") head title=titulo

© FCA – Editora de Informática


Turn static files into dynamic content formats.

Create a flipbook
Issuu converts static files into: digital portfolios, online yearbooks, online catalogs, digital photo albums and more. Sign up and create your flipbook.