Mean: Full stack JavaScript para aplicações web com MongoDB, Express, Angular e Node
Prefácio
É impressionante a quantidade de conhecimento que o Flávio colocou nesse livro. Para mim, esse é o melhor resumo do que você está por encontrar nas próximas páginas.
Você vai aprender uma solução ponta a ponta completíssima usando JavaScript no front-end com Angular, no back-end com Node e Express e no banco de dados com MongoDB. Mas não só. Você vai ver testes de unidade e integração contínua; vai ver build de front-end com Grunt.js e até fazer deploy da aplicação.
O conteúdo me impressiona porque cobre todo o desenvolvimento, apresentando ferramentas para todas as etapas. Isso é muito raro em um livro só. Ao mesmo tempo, o livro é enxuto e na medida certa. Todo o essencial está aqui, mas sem passar do ponto e ser extenso demais.
Se você trabalha com Web, recomendo fortemente o livro. A MEAN Stack com JavaScript em todas as pontas é interessantíssima. Abre muitas possibilidades. Mas vou além e digo que você vai aprender muita coisa aqui, mesmo se não for usar alguma parte do MEAN. Talvez sua aplicação não precise de Angular; mas o conhecimento de Express e Mongo pode-lhe ser útil. Ou talvez você vá usar outro banco de dados, mas vai aprender muito de Angular, Grunt e testes aqui.
Conheço o Flávio há alguns anos já, trabalhando juntos na Caelum. Seu trabalho sempre é pautado por muita seriedade, fundamentação e uma didática incrível. Sempre vi isso em suas aulas e palestras. E agora vejo essas boas características ainda mais acentuadas neste livro. É uma excelente obra, garanto que você vai aproveitar. Boa leitura!
Sérgio Lopes
Agradecimentos
Agradeço a Sérgio Lopes por ter reservado parte do seu escasso tempo para a leitura e elaboração do prefácio deste livro. Aproveito também para agradecer à Casa do Código, mais notadamente ao Adriano Almeida e Vivian Matsui pelo profissionalismo e trato despendidos durante todas as etapas de criação deste livro.
Por fim, não poderia deixar de agradecer à minha esposa Camila Almeida pelo apoio durante os nove meses de gestação deste livro, especialmente por compreender a importância do meu silêncio durante as revisões matinais e noturnas realizadas durante a nossa travessia Niterói/Rio.
Sobre o Autor
Flávio Almeida é desenvolvedor e instrutor na Caelum (http://www.caelum.com.br). Possui mais de 14 anos de experiência na área de desenvolvimento com ampla experiência em segmentos da indústria de shopping centers e varejo. Bacharel em Informática com MBA em Gestão de Negócios em TI. Possui Psicologia como segunda graduação e procura aplicar o que aprendeu no desenvolvimento de software e na educação. Trabalha com a plataforma Java desde 2004, mas atualmente tem focado a plataforma Node.js e a linguagem JavaScript tentando aproximar ainda mais front-end e back-end. Participou das edições 2013 e 2014 da MobileConf e costuma contribuir com o Blog da Caelum (http://blog.caelum.com.br) sobre os mais diversos assuntos. Elabora treinamentos para a plataforma online Alura (http://www.alura.com.br), atividade que vem se tornando cada vez mais prazerosa. Possui uma conta no Twitter (http://twitter.com/flaviohalmeida) e outra no Github (http://github.com/flaviohenriquealmeida).
Sumário
- 1 Introdução
- 1.1 MEAN Stack
- 1.2 Uma aposta no JavaScript
- 1.3 Vantagens da stack
- 1.4 Visão geral da nossa jornada
- 1.5 Instalação do Node.js
- 2 Express: framework web para Node.js
- 2.1 Express e seu papel
- 2.2 Estrutura do projeto e package.json
- 2.3 Instalando o Express através do Npm
- 2.4 Criando o módulo de configuração do Express
- 2.5 Entendendo variáveis de ambiente e middlewares
- 2.6 View e template engine
- 2.7 Configurando rotas
- 2.8 Criando controllers
- 2.9 Carregando dependências com express-load
- 2.10 Listando contatos
- 2.11 Um pouco sobre REST API
- 2.12 Retornando contato da lista
- 3 Bower: gerenciador de dependências front-end
- 3.1 Instalação
- 3.2 bower.json e nossas dependências
- 3.3 Baixando dependências front-end
- 3.4 Alterando a pasta destino com .bowerrc
- 3.5 Outros comandos
- 4 AngularJS: o framework MVC da Google
- 4.1 Um velho conhecido: DOM
- 4.2 Dificuldades que surgem da manipulação do DOM
- 4.3 Características do AngularJS
- 4.4 Preparando o ambiente
- 4.5 Habilitando o AngularJS em nossa página
- 4.6 Nosso primeiro módulo com AngularJS
- 4.7 Angular expression (AE)
- 4.8 Nosso primeiro controlller
- 4.9 $scope: a cola entre controller e view
- 4.10 AngularJS e o model do MVC
- 4.11 Executando ações no controller através de diretiva
- 4.12 A mágica do data binding
- 4.13 Single page application (SPA) e nosso projeto
- 4.14 O módulo ngRoute
- 4.15 Criando views parciais
- 4.16 Configurando rotas com $routeProvider
- 4.17 O objeto $routeParams
- 4.18 Bootstrap: visual profissional em nossas views
- 4.19 A diretiva ng-repeat
- 4.20 A diretiva ng-model e filtragem da lista
- 4.21 Revisando o que aprendemos
- 5 Integrando AngularJS e Express
- 5.1 O serviço $http
- 5.2 Programação assíncrona e callback HELL
- 5.3 Promises: combatendo o callback HELL
- 5.4 Obtendo contatos com $http
- 5.5 O módulo ngResource: trabalhando em alto nível
- 5.6 Consumindo REST Endpoints com $resource
- 5.7 Adicionando rota de exclusão ao Express
- 5.8 Express: organizando melhor nossas rotas
- 5.9 Removendo contatos da lista
- 5.10 As diretivas ng-hide e ng-show
- 5.11 Exibindo contato selecionado
- 5.12 Salvando um contato
- 5.13 Adicionando rota de gravação ao Express
- 5.14 Serviços: organizando melhor nosso código
- 6 MongoDB: banco de dados baseado em documento
- 6.1 Relacional vs. NoSQL: há banco vencedor?
- 6.2 Buscando a menor impedância possível: JSON “everywhere”
- 6.3 Instalação do MongoDB
- 6.4 Utilizando o mongo shell
- 6.5 O conceito de documento
- 6.6 O tipo ObjectId
- 6.7 Criando o banco da aplicação
- 6.8 Collections e inserção de documentos
- 6.9 Buscando documentos
- 6.10 O objeto cursor
- 6.11 Buscando com critério
- 6.12 Query selectors
- 6.13 Indexando documentos
- 6.14 Retornando documentos parciais
- 6.15 Removendo documentos
- 6.16 Atualizando documentos
- 6.17 Realizando upserts
- 6.18 $set: modificador de atualização
- 6.19 Documentos embutidos (Embedded Documents)
- 6.20 Simulando JOINS no lado da aplicação
- 6.21 DBRefs: database references
- 7 Integrando Express e MongoDB
- 7.1 Mongo Driver
- 7.2 Esquema faz falta?
- 7.3 Mongoose Object-Document Modeler
- 7.4 Gerenciando a conexão
- 7.5 Criando esquemas
- 7.6 Utilizando modelos
- 7.7 Buscando documentos
- 7.8 Buscando pelo ID
- 7.9 Removendo documentos
- 7.10 Atualizando documentos
- 7.11 Funções de persistência no Model ou no documento?
- 7.12 Criando referências
- 7.13 Modificando nossa view para exibir emergências
- 7.14 A diretiva ng-options
- 7.15 A função populate e busca de referências
- 8 Autenticação com Passport
- 8.1 OAuth 2.0
- 8.2 Registro no provedor de autenticação
- 8.3 OAuth 2.0 com Passport
- 8.4 Estratégia de autenticação
- 8.5 Definindo Schema do Usuário
- 8.6 Mongoose e plugins
- 8.7 Serialização e desserialização do usuário
- 8.8 Protegendo recursos
- 8.9 Combinando views do servidor/cliente
- 8.10 Implementando Logout
- 8.11 REST Endpoints: permitindo apenas acesso autenticado
- 9 Tornando sua aplicação ainda mais segura
- 9.1 Helmet: middlewares de segurança
- 9.2 MongoDB/API REST: evitando query selector injection
- 9.3 Evitando o document replace
- 9.4 Tratando 404
- 10 Grunt: automação de tarefas front-end
- 10.1 Bem-vindo ao Grunt
- 10.2 O arquivo Gruntfile.js
- 10.3 Instalando nosso primeiro plugin
- 10.4 Tarefas
- 10.5 Targets
- 10.6 Atalho para tarefas
- 10.7 As técnicas de minificação e concatenação
- 10.8 grunt-usemin: minificação e concatenação com Grunt
- 10.9 As tasks usemin e useminPrepare
- 10.10 Angular e minificação
- 11 Testando a aplicação
- 11.1 Karma: feedback instantâneo de testes de unidade
- 11.2 Jasmine: framework de teste
- 11.3 Criando suítes de testes
- 11.4 Rodando suítes de testes através do Karma
- 11.5 Angular-mocks e integração com Jasmine
- 11.6 $httpBackend: “mockando” nosso back-end
- 11.7 Testando de ponta a ponta
- 11.8 Protractor: testes end-to-end com AngularJS
- 11.9 Configurando o Protractor para a aplicação
- 11.10 Automatizando a autenticação do usuário
- 11.11 Testando cenários
- 11.12 PageObject: melhorando a legibilidade e manutenção de testes
- 12 Integração continua
- 12.1 Travis CI
- 12.2 Configurando .travis.yml
- 12.3 Associando seu repositório ao Travis
- 12.4 TaaS: test as a service com SauceLabs
- 12.5 Preparando a aplicação para diferentes ambientes
- 12.6 Integrando Travis e Sauce Labs
- 13 Criando suas próprias diretivas
- 13.1 DDO Directive Definition Object
- 13.2 Isolando o escopo de nossa diretiva
- 13.3 Transclusion
- 13.4 Separando o DDO de seu template
- 13.5 Mais diretivas
- 13.6 Manipulando DOM através de diretiva
- 13.7 A função $watch
- 13.8 Trabalhando com $broadcast
- 13.9 Testando diretivas
- 13.10 Lidando com templateUrl em testes
- 14 Deploy da aplicação
- 14.1 Deploy contínuo
- 14.2 OpenShift: platform as a service (PaaS)
- 14.3 Configurando o ambiente de deploy
- 14.4 Preparando a aplicação para deploy
- 14.5 Integrando Travis com OpenShift
- 14.6 Considerações finais
- Bibliografia
Introdução
"O único homem educado é o homem que aprendeu a aprender"
Alguma vez você já precisou:
- Debugar sua aplicação no navegador, no server e no banco de dados?
- Realizar migrations toda vez que seu esquema de banco mudar?
- Criar um protótipo para rápida validação com o cliente?
- Gerenciar as dependências de seu projeto, tanto do servidor quanto do cliente?
- Automatizar o processo de build de sua aplicação?
- Consumir REST Endpoints diretamente na view?
- Traduzir consultas relacionais em objetos e objetos para o mundo relacional?
- Manipular o DOM adicionando, removendo e alterando elementos dinamicamente?
- Realizar testes unitários e end-to-end?
- Realizar o deploy da aplicação?
- Criar componentes reutilizáveis na view?
Pode parecer um tanto estranho para quem vem procurar respostas em um livro se deparar com uma série de perguntas logo de início.
Agora pense nas linguagens e frameworks que você já utilizou para suprir as necessidades listadas. Pensou? Você provavelmente deve ter chegado a milhões de frameworks e diferentes linguagens, certo? E se eu lhe dissesse que é possível supri-las com apenas uma linguagem, ou melhor, com um quarteto que fala a mesma língua? Seja bem-vindo à MEAN Stack.
1.1 - MEAN Stack
O acrônimo MEAN foi cunhado em 2013 por Valeri Karpov do time do MongoDB * para denotar o uso de uma stack completa para desenvolvimento de aplicações incluindo MongoDB, Express, AngularJS e Node.js:
(M)ongoDB
MongoDB (http://www.mongodb.org) é um poderoso banco de dados NoSQL flexível e escalável. Combina a habilidade de escalar com os muitos recursos presentes nos bancos de dados relacionais como índices, ordenação etc. *.
Na MEAN Stack, MongoDB permite armazenar e reaver um dado em um formato muito similar ao JSON (JavaScript Object Notation) que veremos mais à frente. É um banco fracamente tipado, o que ajuda muito pouco com validação de dados, de modo que boa parte da responsabilidade das regras de validação fica nas mãos dos desenvolvedores.
(E)xpress
Express (http://expressjs.com), criado em 2009 por TJ Holowaychuk, é um framework web light-weight que ajuda na organização de sua aplicação web na arquitetura MVCno lado do servidor. Você pode usar uma série de templates engines como ejs, jade, hogan. Apesar desses engines, na MEAN Stack, o Express geralmente disponibiliza REST Endpoints (http://pt.wikipedia.org/wiki/REST) que são consumidos pelos templates do AngularJs, que por sua vez são atualizados com base nos dados recebidos.
(A)ngularJS
AngularJS (http://angularjs.org/) é um framework MVC no lado do cliente voltado para Single Page Web Applications (SPA) criado pela Google e liberado para o público em 2009. Ele simplifica bastante o desenvolvimento, manutenção e testes. Diferente da maneira tradicional, na qual dado e lógica são processados no servidor, AngularJS facilita o recebimento de dados e execução de lógica diretamente no cliente.
Na MEAN Stack, AngularJS é o responsável por interfaces dinâmicas sem manipulação de DOM e permite acessar facilmente REST Endpoints diretamente do cliente através de serviços especializados.
(N)odeJs
Node.js (http://nodejs.org) é uma plataforma para aplicações JavaScript criada por Ryan Dahl sob o ambiente de execução JavaScript do Chrome. É possível utilizar bibliotecas desenvolvidas pela comunidade através de seu gerenciador de pacotes chamadonpm
.
Na MEAN Stack, Node.js é a condição sine qua non para seu funcionamento, o core.
1.2 - Uma aposta no JavaScript
MEAN aposta na onipresença da linguagem JavaScript, o que significa que a comunidade pode contribuir com novas stacks baseadas em JavaScript na plataforma Node.js que tornem ainda mais produtivo e divertido o desenvolvimento de aplicações web *. Um exemplo disso é a fullstack JavaScript Meteor (https://www.meteor.com), também baseada no Node.js e no MongoDB.
1.3 - Vantagens da stack
Podemos facilmente pensar que, por utilizarmos quatro tecnologias distintas, teremos mais trabalho na implementação e que o desenvolvimento será menos produtivo, certo? Na verdade, para provar o contrário, Karpov utilizou a stack em competições de Hackathon, que são curtas competições de programação, provando o quanto era produtiva. Devido a esta produtividade, a stack foi utilizada em um de seus projetos comerciais, chamado Ascot Project (http://www.ascotproject.com), uma ferramenta de image-tagging para marcar produtos em fotos. É possível ainda listar essas vantagens:
Integração da equipe
A onipresença da linguagem ajuda na integração da equipe: front-end e back-end trabalhando com a mesma linguagem! Isso diminui o truck factor.
Debugging
Debugar a aplicação torna-se mais fácil quando os objetos armazenados no banco de dados são praticamente semelhantes aos objetos no lado do cliente. Por exemplo:
// no navegador
console.log(contato)
{
"_id": "5303e0649fd139619aeb783e"
"nome": "Flávio Almeida"
}
// recebido no servidor
console.log(contato)
{
"_id": "5303e0649fd139619aeb783e"
"nome": "Flávio Almeida"
}
// buscado do banco de dados
console.log(contato)
{
"_id": ObjectId("5303e0649fd139619aeb783e")
"nome": "Flávio Almeida"
}
Repare que o último exemplo devolve um ObjectId, que veremos mais à frente quando abordarmos o MongoDB.
Prototipação
Protótipos ajudam a validar ideias, tomar decisões e descobrir novas possibilidades. Com MEAN, desenvolvedores conseguem protótipos rápidos, já que declaram o modelo como POJO (Plain Old JavaScript Object) no AngularJS, este último utilizado o servidor Express apenas como ponte de acesso ao MongoDB. A estrutura do dado enviado é semelhante no cliente, no servidor e no banco, o que reduz drasticamente o tempo com conversões.
Performance
Há a possibilidade, quando necessária, de processar totalmente ou parcialmente dados e lógica no cliente, onerando menos o servidor.
Build, teste e gerenciamento de dependências
Não é necessário utilizar ferramentas de build ou de gerenciamento de pacotes front-end em outras linguagens, tudo pode ser feito com JavaScript. Veremos como utilizar Grunt (http://gruntjs.com) para automatizar tarefas e Bower (http://bower.io) para gerenciar nossos pacotes de front-end.
Mas como vamos juntar todas essas peças e construir algo rapidamente? Quais passos seguiremos? É o que veremos a seguir.
1.4 - Visão geral da nossa jornada
O ecossistema em torno do JavaScript continua a evoluir. A MEAN Stack é uma tentativa de aproveitá-lo, mas não é um fim em si. Há aqueles que utilizam-na apenas para prototipação, outros por curiosidade ou em aplicações comerciais. Este livro não se coaduna com nenhum desses usos: cabe ao leitor decidir como empregará a stack, mas para isso ele precisa estar informado.
O livro fornecerá uma visão geral da stack no contexto de um CRUD de contatos chamado Contatooh. A instalação do Node.js será nosso ponto de partida. Em seguida, entraremos no Express 4 e aprenderemos como expor REST Endpoints através de rotas. Nesta etapa, não teremos integração com banco, apenas dados voláteis na memória do servidor serão retornados.
Na sequência, passaremos para o AngularJS. Primeiro, vamos aprender seus conceitos fundamentais, para depois integrá-lo com o servidor Express, consumindo os REST Endpoints que foram criados. Aproveitaremos esta etapa para aplicar com zero de esforço um visual profissional à aplicação através do Bootstrap, concluindo a interface da aplicação. Todas as dependências front-end serão baixadas e gerenciadas pelo Bower.
Depois, no lugar de retornarmos e atualizarmos dados voláteis, integraremos nosso back-end Express com o MongoDB através do Mongoose, uma biblioteca que reduz significantemente a quantidade de código utilizada nesta integração.
Ativaremos um sistema de autenticação utilizando o protocolo OAuth 2.0, o que permitirá que apenas usuários autenticados tenham acesso ao sistema. Neste momento, já teremos todas as funcionalidades do projeto prontas.
Com todas as funcionalidades do projeto estabelecidas, automatizaremos tarefas de otimização da aplicação através do Grunt. Vamos criar testes unitários utilizando o Karma/Jasmine e testes end-to-end (e2e) com Protractor.
Integraremos nossa aplicação com o Travis, um servidor de integração contínua gratuito para projetos open source. Inclusive, vamos aprender a rodar nossos testes e2e na nuvem, integrando o Travis com o Sauce Labs, um TaaS( test as a service ) também gratuito para projetos open source. Em seguida, vamos ver como criar e testar nossos próprios componentes de view reutilizáveis através das diretivas do AngularJS.
Por fim, realizaremos o deploy da nossa aplicação no OpenShift, um PaaS ( platform as a service ) que permite o deploy gratuito em seu public PaaS . O deploy será realizado pelo Travis, nosso servidor de integração, apenas se a construção do projeto for bem-sucedida e se todos os testes tiverem passado; isso permite que tenhamos, para cada commit da aplicação, um deploy!
Por que não usar um gerador de código?
Existem na comunidade geradores que fazem scaffold da MEAN Stack que aceleram bastante o tempo de desenvolvimento. Porém, o autor preferiu construir a stack com o leitor, passo a passo, para que você compreenda cada tecnologia individualmente ao mesmo em que integra cada uma delas ao longo do livro.
Não esgotaremos cada tecnologia da composição MEAN, mas o leitor terá a base para se aprofundar ainda mais em cada uma delas. A Casa do Código possui obras que podem ajudá-lo nesta tarefa:
- Aplicações web real-time com Node.js
- REST: Construa API's inteligentes de maneira simples
Você encontra o código apresentado neste livro dividido por capítulo neste endereço (http://github.com/flaviohenriquealmeida/mean-livro-codigo).
Da mesma maneira que um prédio precisa de uma fundação antes de ser construído, a fundação do nosso projeto será o Node.js. Veremos como instalá-lo a seguir.
1.5 - Instalação do Node.js
A instalação do Node.js é tão simples quanto clicar no botão Install
em seu website (http://nodejs.org). O navegador inteligentemente baixará a versão para sua plataforma, seja ela Linux, Mac ou Windows.
Com o arquivo de instalação em mãos, basta executá-lo e seguir o assistente de instalação até o fim. É possível verificar se tudo ocorreu bem executando no terminal o comando node -v na linha de comando.
Linux e Node.js
Nas distribuições Ubuntu e derivadas, pode haver um conflito de nomes quando o Node é instalado pelo apt-get
. Neste caso específico, no lugar do binário se chamar node
, ele passa a se chamar nodejs. Se o seu sistema é uma dessas distribuições, não se preocupe, basta trocar a chamada node
por nodejs
.
Se tudo estiver funcionando, será exibida no console a versão do Node.js instalada:
node -v
v0.10.33
Versões do Node.js superiores a 0.6.2 possuem por padrão o npm instalado, o que facilita ainda mais sua instalação.
Dados do produto
- Número de páginas:
- Data publicação: