From 074785cea106179cb3305637055ab0a009ca74f2 Mon Sep 17 00:00:00 2001 From: Peter Bengtsson Date: Tue, 8 Dec 2020 14:42:52 -0500 Subject: initial commit --- .../ambiente_de_desenvolvimento/index.html | 387 ++++++++++ .../express_nodejs/deployment/index.html | 527 +++++++++++++ .../flow_control_using_async/index.html | 135 ++++ .../express_nodejs/displaying_data/index.html | 87 +++ .../learn/server-side/express_nodejs/index.html | 65 ++ .../introdu\303\247\303\243o/index.html" | 519 +++++++++++++ .../server-side/express_nodejs/mongoose/index.html | 838 +++++++++++++++++++++ .../express_nodejs/skeleton_website/index.html | 509 +++++++++++++ .../tutorial_local_library_website/index.html | 93 +++ 9 files changed, 3160 insertions(+) create mode 100644 files/pt-br/learn/server-side/express_nodejs/ambiente_de_desenvolvimento/index.html create mode 100644 files/pt-br/learn/server-side/express_nodejs/deployment/index.html create mode 100644 files/pt-br/learn/server-side/express_nodejs/displaying_data/flow_control_using_async/index.html create mode 100644 files/pt-br/learn/server-side/express_nodejs/displaying_data/index.html create mode 100644 files/pt-br/learn/server-side/express_nodejs/index.html create mode 100644 "files/pt-br/learn/server-side/express_nodejs/introdu\303\247\303\243o/index.html" create mode 100644 files/pt-br/learn/server-side/express_nodejs/mongoose/index.html create mode 100644 files/pt-br/learn/server-side/express_nodejs/skeleton_website/index.html create mode 100644 files/pt-br/learn/server-side/express_nodejs/tutorial_local_library_website/index.html (limited to 'files/pt-br/learn/server-side/express_nodejs') diff --git a/files/pt-br/learn/server-side/express_nodejs/ambiente_de_desenvolvimento/index.html b/files/pt-br/learn/server-side/express_nodejs/ambiente_de_desenvolvimento/index.html new file mode 100644 index 0000000000..289af21dde --- /dev/null +++ b/files/pt-br/learn/server-side/express_nodejs/ambiente_de_desenvolvimento/index.html @@ -0,0 +1,387 @@ +--- +title: Configurando o Node como ambiente de desenvolvimento +slug: Learn/Server-side/Express_Nodejs/ambiente_de_desenvolvimento +tags: + - Express + - Iniciante + - Introdução + - Node + - nodejs + - npm + - server-side + - web server +translation_of: Learn/Server-side/Express_Nodejs/development_environment +--- +
{{LearnSidebar}}
+ +
{{PreviousMenuNext("Learn/Server-side/Express_Nodejs/Introduction", "Learn/Server-side/Express_Nodejs/Tutorial_local_library_website", "Learn/Server-side/Express_Nodejs")}}
+ +

Agora que você sabe para que serve o Express, nós vamos lhe mostrar como configurar e testar o ambiente Node/Express no Windows, Linux (Ubuntu) e macOS. Independentemente do sistema operacional que você prefere, este artigo deve lhe proporcionar o que você precisa para desenvolver aplicativos em Express.

+ + + + + + + + + + + + +
Pré-Requisitos:Saber como abrir um terminal/linha de comando. Saber como instalar pacotes de software no sistema operacional do computador utilizado para desenvolvimento
Objetivo:Configurar o ambiente de desenvolvimento para Express (X.XX) em seu computador
+ +

Visão geral do ambiente de desenvolvimento do Express

+ +

NodeExpress facilitam a configuração de seu computador para começar a desenvolver aplicações web. Esta seção fornece uma visão ampla de quais ferramentas serão necessárias, explica alguns métodos simples para instalar o Node (e Express) no Ubuntu, macOS e Windows e também mostra como você pode testar sua aplicação.

+ +

O que é o ambiente de desenvolvimento Express?

+ +

O ambiente de desenvolvimento Express inclui uma instalação do Nodejs, o pacote de gerenciamento NPM e (opcionalmente) o Gerador de Aplicações Express em seu computador local.

+ +

O Node e o NPM são instalados em conjunto por meio de um pacote binário preparado, instaladores, pacotes de gerenciamento de sistemas operacionais ou diretamente da fonte (como mostra a seção seguinte). O Express é então instalado pelo NPM como uma dependência de sua aplicação web Express individual (junto a outras bibliotecas como motores de modelo, drivers de banco de dados, autenticações middleware, middleware para arquivos estáticos, etc.)

+ +

NPM também pode ser utilizado para instalar (globalmente) o Express Application Generator, uma ferramenta que cria um "esqueleto" de um app Express, seguindo o padrão MVC. O gerador de app é opcional porque você não precisa dessa ferramenta para criar um app ou um construtor Express para ter a mesma arquitetura. Nós vamos usá-lo nesta seção porque nos permite iniciar uma aplicação de uma maneira mais rápida e promover uma estrutura modular.

+ +
+

Nota: Ao contrário de muitos outros framework que não oferecem um servidor web junto ao ambiente de desenvolvimento, o Node/Express cria e roda o seu próprio servidor web.

+
+ +

Há outras ferramentas periféricas que integram o ambiente de desenvolvimento, é o caso dos editores de textos (códigos), conhecidos como IDE, e versionadores de códigos, como o Git, que ajudam a gerenciar diferentes versões do código. Estamos partindo da ideia de que você já conhece essas ferramentas e as têm instaladas (em especial o editor de texto).

+ +

Quais sistemas operacionais têm suporte?

+ +

Node roda em Windows, macOS, diferentes versões do Linux, Docker, etc. Há uma lista de sistemas suportados que pode ser encontrada na página de Downloads do Nodejs. Quase todos os computadores pessoais têm o que é necessário para rodar o Node. O Express roda no ambiente Node e, consequentemente, roda em qualquer plataforma que roda o Node.

+ +

Neste artigo, vamos abordar as instruções de configuração para Windows, macOS, e Ubuntu Linux.

+ +

Qual versão do Node/Express você deve usar?

+ +

Há várias versões do Node - as mais recentes contém correção de bugs, suporte para EMCAScript (JavaScript) e melhorias nas APIs do Node.

+ +

De maneira geral, você deve usar a versão mais recente do LTS (long-term supported), pois é a mais estável do que a versão "current". Além disso, você deve usar a versão current apenas se precisar de alguma funcionalidade que não está presente na versão LTS.

+ +

Para o Express, você deve usar sempre a versão mais completa.

+ +

Sobre o banco de dados e outras dependências?

+ +

Outras dependências, como database drivers, engine para templates, ferramentas para autenticação, etc, são parte da aplicação e são importadas para o ambiente a partir do NPM. Nós vamos falar sobre essa parte mais para frente.

+ +

Instalando o Node

+ +

Para utilizar o Express, você terá que instalar o Nodejs e o NPM em seu sistema operacional. Nas seções a seguir, vamos explicar o jeito mais fácil de instalar a versão LTS do Nodejs no Ubuntu Linux 16.04, macOS e Windows 10.

+ +
+

Dica: As seções abaixo mostram o jeito mais fácil de instalar o NPM nos Sistemas Operacionais. Se você utilizar outro sistema ou quer ver uma abordagem diferente para as plataformas atuais acesse Instalando Node.js via NPM (nodejs.org).

+
+ +

Windows e macOS

+ +

Instalar o Node e o NPM no Windows ou no macOS é uma tarefa rápida e simples. Siga os seguintes passos:

+ +
    +
  1. Baixar o instalador: +
      +
    1. Vá para https://nodejs.org/en/
    2. +
    3. Selecione o botão de download da versão LTS, que é a recomendada para a maioria dos usuários.
    4. +
    +
  2. +
  3. Instale o Node ao clicar duas vezes no arquivo de download. Siga a instalação a partir das janelas que vão aparecer na sua tela.
  4. +
+ +

Ubuntu 16.04

+ +

O jeito mais fácil de instalar a versão LTS do Node é usar o NPM a partir do Ubuntu binary distributions repository. Isso pode ser feito de uma maneira muito simples. Rode os seguintes comandos no seu terminal.

+ +
curl -sL https://deb.nodesource.com/setup_8.x | sudo -E bash -
+sudo apt-get install -y nodejs
+
+ +
+

Atenção: Não faça a instalação direto do repositório normal do Ubuntu pois ele contém versões antigas do Node.

+
+ +
    +
+ +

Testando a instalação do Nodejs e do NPM

+ +

O jeito mais fácil de testar se tudo correu bem na instalação é checar qual a versão do Node está rodando no computador. Para isso, vá ao terminal/command prompt e digite o seguinte comando para retornar a resposta com a versão mais recente.

+ +
>node -v
+v8.9.4
+ +

O NPM também deve ter sido instalado. Você pode checar da seguinte maneira:

+ +
>npm -v
+5.6.0
+ +

Uma maneira um pouco mais divertida de testar é criar um servidor web em "puro node". Vamos imprimir a tradicional frase "Hello World" no browser quando visitarmos uma determinada URL.

+ +
    +
  1. Crie um arquivo chamado hellonode.js e cole dentro dele o código abaixo. Estamos usando apenas o Node, sem o Express, e com sintaxe do ES6. +
    //Chame o módulo HTTP
    +var http = require("http");
    +
    +//Crie um servidor HTTP para ouvir as requisições na porta 8000
    +http.createServer(function (request, response) {
    +
    +   // Configure o resposta HTTP header com o HTTP status e Content type
    +   response.writeHead(200, {'Content-Type': 'text/plain'});
    +
    +   // Envie a resposta do body "Hello World"
    +   response.end('Hello World\n');
    +}).listen(8000);
    +
    +// Imprima URL para acessar o servidor
    +console.log('Server running at http://127.0.0.1:8000/')
    +
    + +

    O código importa o módulo "http" e o utiliza para criar um servidor (createServer()) que escuta as requisições HTTP na porta 8000. O script, então, imprime a mensagem no console. A função createServer() recebe como argumento uma função callback que é chamada quando recebe uma requisição HTTP - isso retorna uma resposta com um status 200 ("OK") do HTTP e o texto "Hello World".

    +
  2. +
  3. +
    +

    Nota:  Não se preocupe se você não entendeu exatamente o que esse código faz. Nós vamos explicar isso em mais detalhes quando iniciarmos a parte do Express.

    +
    +
  4. +
  5. Inicie o servidor e navegue pelo mesmo diretório que o seu arquivo hellonode.js no terminal. Depois chame o Node da seguinte forma: +
    >node hellonode.js
    +Server running at http://127.0.0.1:8000/
    +
    +
  6. +
  7. Navegue até a URL (http://127.0.0.1:8000/). Se tudo estiver funcionando bem, o browser vai apresentar a frase "Hello World".
  8. +
+ +

Usando o NPM

+ +

Ao lado do próprio Node, o NPM é a ferramenta de trabalho mais importante nas aplicações Node. O NPM é usado para buscar qualquer pacote (biblioteca JavaScript) que uma aplicação precisa para ser desenvolvida, testada ou produzida, além de ser adotado para rodar testes ao longo de todo o processo de desenvolvimento.

+ +
+

Nota: A partir da perspectiva do Node, Express é um pacote que precisa ser instalado utilizando o NPM e depois importado para o seu código.

+
+ +

Você pode usar o NPM separadamente para buscar cada pacote desejado. Em geral, nós gerenciamos as dependências com um arquivo chamado package.json. Esse arquivo lista todas as dependências para um pacote JavaScript específico, incluindo o nome do pacote, a versão, descrição, arquivo de inicialização, produção de dependências, desenvolvimento de dependências, versões do Node que podem ser utilizadas. O package.json contém tudo que o NPM precisa para buscar e rodar a sua aplicação (se você está escrevendo uma biblioteca para ser reutilizável, você pode usar essa definição para fazer o upload do pacote para o repositório npm e deixá-lo acessível a qualquer usuário).

+ +

Adicionando dependências

+ +

Os passos seguintes mostram como baixar pacotes via NPM, salvá-los nas dependências do projeto e importá-los/chamá-los para dentro da aplicação Node.

+ +
+

Nota:  Nesta seção mostraremos como buscar e instalar o pacote do Express. Depois, explicaremos como esse e outros pacotes já estão especificados para nós graças ao Express Application Generator. É  muito importante entendermos como o NPM funciona e o que é criado com o generator. 

+
+ +
    +
  1. Primeiro passo é criar um diretório para sua aplicação. No prompt, insira os comandos a seguir. +
    mkdir myapp
    +cd myapp
    +
  2. +
  3.  Use o comando npm init para criar o arquivo package.json da sua aplicação. Esse comando registra para você uma série de informações, como o nome e a versão do seu aplicativo, além do nome do seu "entry point" (index.js por padrão). Por hora, vamos manter a configuração padrão. +
    npm init
    + +

    Se você acessar o arquivo package.json (cat packge.json), você verá toda a configuração padrão e, ao final, o tipo de licença que o app está utilizando.

    + +
    {
    +  "name": "myapp",
    +  "version": "1.0.0",
    +  "description": "",
    +  "main": "index.js",
    +  "scripts": {
    +    "test": "echo \"Error: no test specified\" && exit 1"
    +  },
    +  "author": "",
    +  "license": "ISC"
    +}
    +
    +
  4. +
  5. Agora, instale o Express dentro do diretório myapp. O pacote será salvo automaticamente na lista de dependências do seu package.json.
  6. +
  7. +
    npm install express
    + +

    A lista de dependências do package.json agora mostra também a versão do Express que estamos usando. Está grifada no final do arquivo.

    + +
    {
    +  "name": "myapp",
    +  "version": "1.0.0",
    +  "description": "",
    +  "main": "index.js",
    +  "scripts": {
    +    "test": "echo \"Error: no test specified\" && exit 1"
    +  },
    +  "author": "",
    +  "license": "ISC",
    +  "dependencies": {
    +    "express": "^4.16.2"
    +  }
    +}
    +
    +
  8. +
  9. Para usar o Express, é preciso incluir a função require() no arquivo index.js dentro da sua aplicação. Crie esse arquivo agora mesmo na pasta raiz "myapp" e inclua o código a seguir. +
    var express = require('express')
    +var app = express()
    +
    +app.get('/', function (req, res) {
    +  res.send('Hello World!')
    +})
    +
    +app.listen(8000, function () {
    +  console.log('Example app listening on port 8000!')
    +})
    +
    + +

    O código mostra uma aplicação web bem simples cujo objetivo único é imprimir a mensagem "HelloWorld". Em linhas gerais, esse arquivo importa o módulo do express e o utiliza para criar um servidor (app) que escuta as requisições HTTP pela porta 8000 e imprime a mensagem no console, além de definir qual URL usada para testar o servidor. A função app.get() responde apenas às requisições HTTP feitas com o método GET, desde que especificadas com o path ('/'). Nesse caso, chamando a função para enviar a mensagem Hello World!

    +
  10. +
  11. Rode a linha de comando abaixo para iniciar o servidor. +
    >node index.js
    +Example app listening on port 8000
    +
    +
  12. +
  13. Vá para a seguinte URL (http://127.0.0.1:8000/). Se tudo estiver funcionando corretamente, o browser vai mostrar a mensagem "Hello World!".
  14. +
+ +

Desenvolvendo dependências

+ +

Se você utilizar uma dependência apenas durante o desenvolvimento da aplicação, é recomendado que você a salve como uma "development dependency". Dessa forma, o pacote não será utilizado no ambiente de produção. Por exemplo: caso utilizar o pacote esling (JavaScript Linting), você faria a instalação via NPM da seguinte forma.

+ +
npm install eslint --save-dev
+ +

Assim, a esling vai aparecer da seguinte forma na lista de dependências do package.json.

+ +
  "devDependencies": {
+    "eslint": "^4.12.1"
+  }
+
+ +
+

Note: "Linters" são ferramentas que nos ajudam a identificar e reportar que o código está sendo escrito dentro das melhores práticas.

+
+ +

Rodando tarefas

+ +

Além de definir e buscar dependências, você também pode nomear scripts dentro do seu arquivo package.json e chamar o NPM para executá-lo a partir de um run-script command. Essa abordagem é comum para automatizar testes e tarefas ao longo do desenvolvimento (por exemplo: minificar o JavaScript, reduzir imagens, LINT/análise de códigos, etc).

+ +
+

Nota: Ferramentas de automação de tarefas como o Gulp e o Grunt também podem ser utilizados, além de outros pacotes externos. 

+
+ +

Para definir o script que roda o esling, citado na seção acima, nós precisamos adicionar o seguinte bloco no nosso package.json (importante: sua aplicação precisa ter como source está na pasta /src/js):

+ +
"scripts": {
+  ...
+  "lint": "eslint src/js"
+  ...
+}
+
+ +

Explicando um pouco mais: eslint src/js é o comando que colocamos no nosso terminal para rodar o eslint nos arquivos JavaScript situados no diretório src/js dentro do diretório do nosso app. Incluindo o comando, criamos o comando de atalho - lint.

+ +
npm run-script lint
+# OR (using the alias)
+npm run lint
+
+ +

O exemplo pode não parecer mais curto do que o comando original, mas com o que você aprendeu é possível incluir comandos bem maiores dentro do npm scripts, como as cadeias de múltiplos comandos. Você pode até escrever um único script npm para rodar todos os seus testes de uma só vez.

+ +

Instalando o Express Application Generator

+ +

Express Application Generator é uma ferramenta que cria "esqueleto" para aplicações Express. A instalação é realizada via NPM como mostrada a seguir (o comando -g instala a pacote globalmente, ou seja, você pode acessá-lo de qualquer lugar do seu computador).

+ +
npm install express-generator -g
+ +

Para criar um aplicativo Express chamado "helloworld" com as configurações padrões, vá até o local/pasta em que você deseja desenvolver o projeto e escreva a seguinte linha de comando:

+ +
express helloworld
+ +
+

Nota:  Você também pode definir a biblioteca de template que pretende usar e muitas outras configurações. Use o comando help para ver todas as opções. 

+ +
express --help
+
+
+ +

O NPM vai criar um novo aplicativo Express em uma subpasta na localização em que você está. O progresso será apresentado no console. Para finalizar, o processo, a ferramenta mostrará os comandos que você precisa seguir para instalar a dependência Node e iniciar o seu app.

+ +
+

O novo app terá um arquivo package.json no diretório raiz. Você pode abrir esse arquivo para checar o que foi instalado, incluindo o Express e Jade (template library) .

+ +
{
+  "name": "helloworld",
+  "version": "0.0.0",
+  "private": true,
+  "scripts": {
+    "start": "node ./bin/www"
+  },
+  "dependencies": {
+    "body-parser": "~1.18.2",
+    "cookie-parser": "~1.4.3",
+    "debug": "~2.6.9",
+    "express": "~4.15.5",
+    "jade": "~1.11.0",
+    "morgan": "~1.9.0",
+    "serve-favicon": "~2.4.5"
+  }
+}
+
+ +

Instale todas as dependências para o app helloworld com o NPM, de acordo com os comandos abaixo:

+ +
cd helloworld
+npm install
+
+ +

Agora, rode o aplicativo (o comando muda um pouco entre Windows, Linux/macOS), como está no código a seguir:

+ +
# Rode o helloworld no Windows
+SET DEBUG=helloworld:* & npm start
+
+# Rode helloworld no Linux/macOS
+DEBUG=helloworld:* npm start
+
+ +

O comando DEBUG gera um loggin bem útil, apresentando resultados, como abaixo:

+ +
>SET DEBUG=helloworld:* & npm start
+
+> helloworld@0.0.0 start D:\Github\expresstests\helloworld
+> node ./bin/www
+
+  helloworld:server Listening on port 3000 +0ms
+ +

Abre um browser e navegue para http://127.0.0.1:3000/ e veja a página default apresentada pelo aplicativo.

+ +

Express - Generated App Default Screen

+ +

Vamos falar mais sobre o "gerador" quando chegarmos ao artigo referente à geração de esqueletos de uma aplicação.

+ + + +

Sumário

+ +

Agora você tem o desenvolvimento do Node pronto para rodar no seu computador e que pode ser utilizado para criar aplicações web com o framework Express. Você também viu como o NPM é utilizado para importar o Express em sua aplicação e como criar um esqueleto a partir do Express Aplication Generator.

+ +

No próximo artigo, nós vamos iniciar um tutorial para construir uma aplicação web completa utilizando esse ambiente junto com as ferramentas.

+ +

Veja também

+ + + +

{{PreviousMenuNext("Learn/Server-side/Express_Nodejs/Introduction", "Learn/Server-side/Express_Nodejs/Tutorial_local_library_website", "Learn/Server-side/Express_Nodejs")}}

+ +

Outros módulos

+ + diff --git a/files/pt-br/learn/server-side/express_nodejs/deployment/index.html b/files/pt-br/learn/server-side/express_nodejs/deployment/index.html new file mode 100644 index 0000000000..77e9914e87 --- /dev/null +++ b/files/pt-br/learn/server-side/express_nodejs/deployment/index.html @@ -0,0 +1,527 @@ +--- +title: 'Express Tutorial Part 7: Deploying to production' +slug: Learn/Server-side/Express_Nodejs/deployment +tags: + - Express + - Implantação + - Iniciante + - Node + - aprendizado + - heroku +translation_of: Learn/Server-side/Express_Nodejs/deployment +--- +
{{LearnSidebar}}
+ +
{{PreviousMenu("Learn/Server-side/Express_Nodejs/forms", "Learn/Server-side/Express_Nodejs")}}
+ +

Now you've created (and tested) an awesome LocalLibrary website, you're going to want to install it on a public web server so that it can be accessed by library staff and members over the Internet. This article provides an overview of how you might go about finding a host to deploy your website, and what you need to do in order to get your site ready for production.

+ + + + + + + + + + + + +
Pré-requisitos:Complete todos os tópicos anteriores do turotrial, inclusive o Express Tutorial Part 6: Working with forms.
Objetivo:Aprender onde e como você pode implantar um app Express app em produção.
+ +

Overview

+ +

Once your site is finished (or finished "enough" to start public testing) you're going to need to host it somewhere more public and accessible than your personal development computer.

+ +

Up to now you've been working in a development environment, using Express/Node as a web server to share your site to the local browser/network, and running your website with (insecure) development settings that expose debugging and other private information. Before you can host a website externally you're first going to have to:

+ + + +

This tutorial provides some guidance on your options for choosing a hosting site, a brief overview of what you need to do in order to get your Express app ready for production, and a worked example of how to install the LocalLibrary website onto the Heroku cloud hosting service.

+ +

Bear in mind that you don't have to use Heroku — there are other hosting service available. We've also provided a separate tutorial to show how to Install LocalLibrary on PWS/Cloud Foundry.

+ +

What is a production environment?

+ +

The production environment is the environment provided by the server computer where you will run your website for external consumption. The environment includes:

+ + + +

The server computer could be located on your premises and connected to the Internet by a fast link, but it is far more common to use a computer that is hosted "in the cloud". What this actually means is that your code is run on some remote computer (or possibly a "virtual" computer) in your hosting company's data center(s). The remote server will usually offer some guaranteed level of computing resources (e.g. CPU, RAM, storage memory, etc.) and Internet connectivity for a certain price.

+ +

This sort of remotely accessible computing/networking hardware is referred to as Infrastructure as a Service (IaaS). Many IaaS vendors provide options to preinstall a particular operating system, onto which you must install the other components of your production environment. Other vendors allow you to select more fully-featured environments, perhaps including a complete Node setup.

+ +
+

Note: Pre-built environments can make setting up your website very easy because they reduce the configuration, but the available options may limit you to an unfamiliar server (or other components) and may be based on an older version of the OS. Often it is better to install components yourself, so that you get the ones that you want, and when you need to upgrade parts of the system, you have some idea of where to start!

+
+ +

Other hosting providers support Express as part of a Platform as a Service (PaaS) offering. When using this sort of hosting you don't need to worry about most of your production environment (servers, load balancers, etc.) as the host platform takes care of those for you. That makes deployment quite easy, because you just need to concentrate on your web application and not any other server infrastructure.

+ +

Some developers will choose the increased flexibility provided by IaaS over PaaS, while others will appreciate the reduced maintenance overhead and easier scaling of PaaS. When you're getting started, setting up your website on a PaaS system is much easier, so that is what we'll do in this tutorial.

+ +
+

Tip: If you choose a Node/Express-friendly hosting provider they should provide instructions on how to set up an Express website using different configurations of webserver, application server, reverse proxy, etc. For example, there are many step-by-step guides for various configurations in the Digital Ocean Node community docs.

+
+ +

Choosing a hosting provider

+ +

There are numerous hosting providers that are known to either actively support or work well with Node (and Express). These vendors provide different types of environments (IaaS, PaaS), and different levels of computing and network resources at different prices.

+ +
+

Tip: There are a lot of hosting solutions, and their services and pricing can change over time. While we introduce a few options below, it is worth performing your own Internet search before selecting a hosting provider.

+
+ +

Some of the things to consider when choosing a host:

+ + + +

The good news when you're starting out is that there are quite a few sites that provide computing environments for "free", albeit with some conditions. For example, Heroku provides a free but resource-limited PaaS environment "forever", while Amazon Web Services, Microsoft Azure, and the open source option PWS/Cloud Foundry provide free credit when you first join.

+ +

Many providers also have a "basic" tier that provides more useful levels of computing power and fewer limitations. Digital Ocean is an example of a popular hosting provider that offers a relatively inexpensive basic computing tier (in the $5 per month lower range at time of writing).

+ +
+

Note: Remember that price is not the only selection criterion. If your website is successful, it may turn out that scalability is the most important consideration.

+
+ +

Getting your website ready to publish

+ +

The main things to think about when publishing your website are web security and performance. At the bare minimum, you will want to remove the stack traces that are included on error pages during development, tidy up your logging, and set the appropriate headers to avoid many common security threats.

+ +

In the following subsections we outline the most important changes that you should make to your app.

+ +
+

Tip: There are other useful tips in the Express docs — see Production best practices: performance and reliability and Production Best Practices: Security.

+
+ +

Set NODE_ENV to 'production'

+ +

We can remove stack traces in error pages by setting the NODE_ENV environment variable to production (it is set to 'development' by default). In addition to generating less-verbose error messages, setting the variable to production caches view templates and CSS files generated from CSS extensions. Tests indicate that setting NODE_ENV to production can improve app performance by a factor of three!

+ +

This change can be made either by using export or an environment file, or using the OS initialisation system.  

+ +
+

Note: This is actually a change you make in your environment setup rather than your app, but important enough to note here! We'll show how this is set for our hosting example below. 

+
+ +

Log appropriately

+ +

Logging calls can have an impact on a high-traffic website. In a production environment you may need to log website activity (e.g. tracking traffic or logging API calls) but you should attempt to minimise the amount of logging added for debugging purposes.

+ +

One way to minimise "debug" logging in production is to use a module like debug that allows you to control what logging is performed by setting an environment variable. For example, the code fragment below shows how you might  set up "author" logging. The debug variable is declared with the name 'author', and the prefix "author" will be automatically displayed for all logs from this object.

+ +
var debug = require('debug')('author');
+
+// Display Author update form on GET
+exports.author_update_get = function(req, res, next) {
+
+    req.sanitize('id').escape().trim();
+    Author.findById(req.params.id, function(err, author) {
+        if (err) {
+            debug('update error:' + err);
+            return next(err);
+        }
+        //On success
+        res.render('author_form', { title: 'Update Author', author: author });
+    });
+
+};
+ +

You can then enable a particular set of logs by specifying them as a comma-separated list in the DEBUG environment variable. You can set the variables for displaying author and book logs as shown (wildcards are also supported).

+ +
#Windows
+set DEBUG=author,book
+
+#Linux
+export DEBUG="author,book"
+
+ +
+

Challenge: Calls to debug can replace logging you might previously have done using console.log() or console.error(). Replace any console.log() calls in your code with logging via the debug module. Turn the logging on and off in your development environment by setting the DEBUG variable and observe the impact this has on logging.

+
+ +

If you need to log website activity you can use a logging library like Winston or Bunyan. For more information on this topic see: Production best practices: performance and reliability.

+ +

Use gzip/deflate compression for responses

+ +

Web servers can often compress the HTTP response sent back to a client, significantly reducing the time taken to for the client to get and load the page. The compression method used will depend on what decompression methods the client says that it supports in the request (if no compression methods are supported the response will be sent uncompressed).

+ +

You can add this to your site using compression middleware. Install this to your project by running the following command at the root of the project.

+ +
npm install compression
+ +

Open ./app.js and require the compression library as shown. Add the compression library to the middleware chain with the use() method (this should appear before any routes that you want compressed — in this case all of them!)

+ +
var catalog = require('./routes/catalog'); //Import routes for "catalog" area of site
+var compression = require('compression');
+
+// Create the Express application object
+var app = express();
+
+...
+
+app.use(compression()); //Compress all routes
+
+app.use(express.static(path.join(__dirname, 'public')));
+
+app.use('/', index);
+app.use('/users', users);
+app.use('/catalog', catalog);  // Add catalog routes to middleware chain.
+
+...
+
+ +
+

Note: For a high-traffic website in production you wouldn't use this middleware. Instead you would use a reverse proxy like Nginx.

+
+ +

Use Helmet to protect against well known vulnerabilities

+ +

Helmet is a middleware package that can help protect your app from some well-known web vulnerabilities by setting appropriate HTTP headers (see the docs for more information on what headers it sets/vulnerabilities it protects against). 

+ +

Install this to your project by running the following command at the root of the project.

+ +
npm install helmet
+
+ +

Open ./app.js and require the helmet library as shown. Then add the module to the middleware chain with the use() method.

+ +
var compression = require('compression');
+var helmet = require('helmet');
+
+// Create the Express application object
+var app = express();
+
+app.use(helmet());
+...
+ +
+

Note: The command above adds the subset of available headers that makes sense for most sites. You can add/disable specific headers as needed by following the instructions on npm.

+
+ +

Example: Installing LocalLibrary on Heroku

+ +

This section provides a practical demonstration of how to install LocalLibrary on the Heroku PaaS cloud.

+ +

Why Heroku?

+ +

Heroku is one of the longest running and popular cloud-based PaaS services. It originally supported only Ruby apps, but now can be used to host apps from many programming environments, including Node (and hence Express)!

+ +

We are choosing to use Heroku for several reasons:

+ + + +

While Heroku is perfect for hosting this demonstration it may not be perfect for your real website. Heroku makes things easy to set up and scale, at the cost of being less flexible, and potentially a lot more expensive once you get out of the free tier.

+ +

How does Heroku work?

+ +

Heroku runs websites within one or more "Dynos", which are isolated, virtualized Unix containers that provide the environment required to run an application. The dynos are completely isolated and have an ephemeral file system (a short-lived file system that is cleaned/emptied every time the dyno restarts). The only thing that dynos share by default are application configuration variables. Heroku internally uses a load balancer to distribute web traffic to all "web" dynos. Since nothing is shared between them, Heroku can scale an app horizontally by adding more dynos (though of course you may also need to scale your database to accept additional connections).

+ +

Because the file system is ephemeral you can't install services required by your application directly (e.g. databases, queues, caching systems, storage, email services, etc). Instead Heroku web applications use backing services provided as independent "add-ons" by Heroku or 3rd parties. Once attached to your web application, the add-on services are accessed in your web application via environment variables.

+ +

In order to execute your application Heroku needs to be able to set up the appropriate environment and dependencies, and also understand how it is launched. For Node apps all the information it needs is obtained from your package.json file.

+ +

Developers interact with Heroku using a special client app/terminal, which is much like a Unix bash script. This allows you to upload code that is stored in a git repository, inspect the running processes, see logs, set configuration variables, and much more!

+ +

In order to get our application to work on Heroku we'll need to put our Express web application into a git repository and make some minor changes to the package.json. Once we've done that we can set up a Heroku account, get the Heroku client, and use it to install our website.

+ +

That's all the overview you need in order to get started (see Getting Started on Heroku with Node.js for a more comprehensive guide).

+ +

Creating an application repository in Github

+ +

Heroku is closely integrated with the git source code version control system, using it to upload/synchronise any changes you make to the live system. It does this by adding a new Heroku "remote" repository named heroku pointing to a repository for your source on the Heroku cloud. During development you use git to store changes on your "master" repository. When you want to deploy your site, you sync your changes to the Heroku repository.

+ +
+

Note: If you're used to following good software development practices you are probably already using git or some other SCM system. If you already have a git repository, then you can skip this step.

+
+ +

There are a lot of ways of to work with git, but one of the easiest is to first set up an account on GitHub, create the repository there, and then sync to it locally:

+ +
    +
  1. Visit https://github.com/ and create an account.
  2. +
  3. Once you are logged in, click the + link in the top toolbar and select New repository.
  4. +
  5. Fill in all the fields on this form. While these are not compulsory, they are strongly recommended. +
      +
    • Enter a new repository name (e.g. express-locallibrary-tutorial), and description (e.g. "Local Library website written in Express (Node)".
    • +
    • Choose Node in the Add .gitignore selection list.
    • +
    • Choose your preferred license in the Add license selection list.
    • +
    • Check Initialize this repository with a README.
    • +
    +
  6. +
  7. Press Create repository.
  8. +
  9. Click the green "Clone or download" button on your new repo page.
  10. +
  11. Copy the URL value from the text field inside the dialog box that appears (it should be something like: https://github.com/<your_git_user_id>/express-locallibrary-tutorial.git).
  12. +
+ +

Now the repository ("repo") is created we are going to want to clone it on our local computer:

+ +
    +
  1. Install git for your local computer (you can find versions for different platforms here).
  2. +
  3. Open a command prompt/terminal and clone your repository using the URL you copied above: +
    git clone https://github.com/<your_git_user_id>/express-locallibrary-tutorial.git
    +
    + This will create the repository below the current point.
  4. +
  5. Navigate into the new repo. +
    cd express-locallibrary-tutorial
    +
  6. +
+ +

The final step is to copy in your application and then add the files to your repo using git:

+ +
    +
  1. Copy your Express application into this folder (excluding /node_modules, which contains dependency files that you should fetch from NPM as needed).
  2. +
  3. Open a command prompt/terminal and use the add command to add all files to git.
  4. +
  5. +
    git add -A
    +
    +
  6. +
  7. Use the status command to check all files that you are about to add are correct (you want to include source files, not binaries, temporary files etc.). It should look a bit like the listing below. +
    > git status
    +On branch master
    +Your branch is up-to-date with 'origin/master'.
    +Changes to be committed:
    +  (use "git reset HEAD <file>..." to unstage)
    +
    +        new file:   ...
    +
  8. +
  9. When you're satisfied commit the files to your local repository: +
    git commit -m "First version of application moved into github"
    +
  10. +
  11. Then synchronise your local repository to the Github website, using the following: +
    git push origin master
    +
  12. +
+ +

When this operation completes, you should be able to go back to the page on Github where you created your repo, refresh the page, and see that your whole application has now been uploaded. You can continue to update your repository as files change using this add/commit/push cycle.

+ +
+

Tip: This is a good point to make a backup of your "vanilla" project — while some of the changes we're going to be making in the following sections might be useful for deployment on any platform (or development) others might not.

+ +

The best way to do this is to use git to manage your revisions. With git you can not only go back to a particular old version, but you can maintain this in a separate "branch" from your production changes and cherry-pick any changes to move between production and development branches. Learning Git is well worth the effort, but is beyond the scope of this topic.

+ +

The easiest way to do this is to just copy your files into another location. Use whichever approach best matches your knowledge of git!

+
+ +

Update the app for Heroku

+ +

This section explains the changes you'll need to make to our LocalLibrary application to get it to work on Heroku.

+ +

Set node version 

+ +

The package.json contains everything needed to work out your application dependencies and what file should be launched to start your site. Heroku detects the presence of this file, and will use it to provision your app environment.

+ +

The only useful information missing in our current package.json is the version of node. We can find the version of node we're using for development by entering the command:

+ +
>node --version
+v8.9.1
+ +

Open package.json, and add this information as an engines > node section as shown (using the version number for your system).

+ +
{
+  "name": "express-locallibrary-tutorial",
+  "version": "0.0.0",
+  "engines": {
+    "node": "8.9.1"
+  },
+  "private": true,
+  ...
+
+ +

Database configuration

+ +

So far in this tutorial we've used a single database that is hard coded into app.js. Normally we'd like to be able to have a different database for production and development, so next we'll modify the LocalLibrary website to get the database URI from the OS environment (if it has been defined), and otherwise use our development database.

+ +

Open app.js and find the line that sets the mongoDB connection variable. It will look something like this:

+ +
var mongoDB = 'mongodb://your_user_id:your_password@ds119748.mlab.com:19748/local_library';
+ +

Replace the line with the following code that uses process.env.MONGODB_URI to get the connection string from an environment variable named MONGODB_URI if has been set (use your own database URL instead of the placeholder below.)

+ +
var mongoDB = process.env.MONGODB_URI || 'mongodb://your_user_id:your_password@ds119748.mlab.com:19748/local_library';
+
+ +

Get dependencies and re-test

+ +

Before we proceed, let's test the site again and make sure it wasn't affected by any of our changes. 

+ +

First we will need to fetch our dependencies (you will recall we didn't copy the node_modules folder into our git tree). You can do this by running the following command in your terminal at the root of the project:

+ +
npm install
+
+ +

Now run the site (see Testing the routes for the relevant commands) and check that the site still behaves as you expect.

+ +

Save changes to Github

+ +

Next let's save all our changes to Github. In the terminal (whilst inside our repository), enter the following commands:

+ +
git add -A
+git commit -m "Added files and changes required for deployment to heroku"
+git push origin master
+ +

We should now be ready to start deploying LocalLibrary on Heroku.

+ +

Get a Heroku account

+ +

To start using Heroku you will first need to create an account (skip ahead to Create and upload the website if you've already got an account and installed the Heroku client):

+ + + +

Install the client

+ +

Download and install the Heroku client by following the instructions on Heroku here.

+ +

After the client is installed you will be able run commands. For example to get help on the client:

+ +
heroku help
+
+ +

Create and upload the website

+ +

To create the app we run the "create" command in the root directory of our repository. This creates a git remote ("pointer to a remote repository") named heroku in our local git environment.

+ +
heroku create
+ +
+

Note: You can name the remote if you like by specifying a value after "create". If you don't then you'll get a random name. The name is used in the default URL.

+
+ +

We can then push our app to the Heroku repository as shown below. This will upload the app, get all its dependencies, package it in a dyno, and start the site.

+ +
git push heroku master
+ +

If we're lucky, the app is now "running" on the site. To open your browser and run the new website, use the command:

+ +
heroku open
+ +
+

Note: The site will be running using our development database. Create some books and other objects, and check out whether the site is behaving as you expect. In the next section we'll set it to use our new database.

+
+ +

Setting configuration variables

+ +

You will recall from a preceding section that we need to set NODE_ENV to 'production' in order to improve our performance and generate less-verbose error messages. We do this by entering the following command:

+ +
>heroku config:set NODE_ENV='production'
+Setting NODE_ENV and restarting limitless-tor-18923... done, v13
+NODE_ENV: production
+
+ +

We should also use a separate database for production, setting its URI in the MONGODB_URI  environment variable. You can set up a new database and database-user exactly as we did originally, and get its URI. You can set the URI as shown (obviously, using your own URI!)

+ +
>heroku config:set MONGODB_URI='mongodb://your_user:your_password@ds139278.mlab.com:39278/local_library_production'
+Setting MONGODB_URI and restarting limitless-tor-18923... done, v13
+MONGODB_URI: mongodb://your_user:your_password@ds139278.mlab.com:39278/local_library_production
+
+ +

You can inspect your configuration variables at any time using the heroku config command — try this now:

+ +
>heroku config
+=== limitless-tor-18923 Config Vars
+MONGODB_URI: mongodb://your_user:your_password@ds139278.mlab.com:39278/local_library_production
+NODE_ENV:    production
+
+ +

Heroku will restart your app when it updates the variables. If you check the home page now it should show zero values for your object counts, as the changes above mean that we're now using a new (empty) database.

+ +

Managing addons

+ +

Heroku uses independent add-ons to provide backing services to apps — for example email or database services. We don't use any addons in this website, but they are an important part of working with Heroku, so you may want to check out the topic Managing Add-ons (Heroku docs).

+ +

Debugging

+ +

The Heroku client provides a few tools for debugging:

+ +
heroku logs  # Show current logs
+heroku logs --tail # Show current logs and keep updating with any new results
+heroku ps   #Display dyno status
+
+ + + +

Summary

+ +

That's the end of this tutorial on setting up Express apps in production, and also the series of tutorials on working with Express. We hope you've found them useful. You can check out a fully worked-through version of the source code on Github here.

+ +

See also

+ + + +

{{PreviousMenu("Learn/Server-side/Express_Nodejs/forms", "Learn/Server-side/Express_Nodejs")}}

+ +

 

+ +

In this module

+ + + +

 

diff --git a/files/pt-br/learn/server-side/express_nodejs/displaying_data/flow_control_using_async/index.html b/files/pt-br/learn/server-side/express_nodejs/displaying_data/flow_control_using_async/index.html new file mode 100644 index 0000000000..1f4b09375b --- /dev/null +++ b/files/pt-br/learn/server-side/express_nodejs/displaying_data/flow_control_using_async/index.html @@ -0,0 +1,135 @@ +--- +title: Controle de fluxo assíncrono usando async +slug: Learn/Server-side/Express_Nodejs/Displaying_data/flow_control_using_async +translation_of: Learn/Server-side/Express_Nodejs/Displaying_data/flow_control_using_async +--- +

O código da Controller, para algumas de nossas páginas dependerá dos resultados de várias solicitações assíncronas, que talvez possam ser necessárias para serem executadas em uma ordem específica ou em paralelo. Para gerenciar o controle do nosso fluxo e renderizar páginas quando tivermos todas as informações necessárias disponíveis, usaremos o popular módulo async.

+ +
+

Nota: Há várias outras maneiras de gerenciar o comportamento assíncrono e o controle de fluxo em JavaScript, um dos recursos Javascript que pode ser utilizado, são as Promises

+
+ +

Async has a lot of useful methods (check out the documentation). Some of the more important functions are:

+ + + +

Por que isso é necessário ?

+ +

A maioria dos métodos que usamos no Express são assíncronos - você especifica uma operação para executar, passando um callback. O método retorna imediatamente e o callback é invocado quando a operação solicitada é concluída. Por convenção no Express, as funções de callback passam um valor de erro como o primeiro parâmetro (ou nulo em sucesso) e os resultados da função (se houver algum) como o segundo parâmetro.

+ +

Se uma Controller só precisa executar uma operação assíncrona para obter as informações necessárias para renderizar uma página, a implementação é fácil —simplesmente renderizamos o template no callback. O código abaixo ilustra uma função que renderiza a contagem de um model ExampleModel (usando o método count()  do Mongoose.

+ +
exports.example_model_count = function(req, res, next) {
+
+  ExampleModel .count({ a_model_field: 'match_value' }, function (err, count) {
+    // ... do something if there is an err
+
+    // On success, render the result by passing count into the render function (here, as the variable 'data').
+    res.render('the_template', { data: count } );
+  });
+}
+
+ +

However what if you need to make multiple asynchronous queries, and you can't render the page until all the operations have completed? A naive implementation could "daisy chain" the requests, kicking off subsequent requests in the callback of a previous request, and rendering the response in the final callback. The problem with this approach is that our requests would have to be run in series, even though it might be more efficient to run them in parallel. This could also result in complicated nested code, commonly referred to as callback hell.

+ +

A much better solution would be to execute all the requests in parallel and then have a single callback that executes when all of the queries have completed. This is the sort of flow operation that the Async module makes easy!

+ +

Operações assíncronas em paralelo

+ +

The method async.parallel() is used to run multiple asynchronous operations in parallel.

+ +

The first argument to async.parallel() is a collection of the asynchronous functions to run (an array, object or other iterable). Each function is passed a callback(err, result) which it must call on completion with an error err (which can be null) and an optional results value.

+ +

The optional second argument to  async.parallel() is a callback that will be run when all the functions in the first argument have completed. The callback is invoked with an error argument and a result collection that contains the results of the individual asynchronous operations. The result collection is of the same type as the first argument (i.e. if you pass an array of asynchronous functions, the final callback will be invoked with an array of results). If any of the parallel functions reports an error the callback is invoked early (with the error value).

+ +

The example below shows how this works when we pass an object as the first argument. As you can see, the results are returned in an object with the same property names as the original functions that were passed in.

+ +
async.parallel({
+  one: function(callback) { ... },
+  two: function(callback) { ... },
+  ...
+  something_else: function(callback) { ... }
+  },
+  // optional callback
+  function(err, results) {
+    // 'results' is now equal to: {one: 1, two: 2, ..., something_else: some_value}
+  }
+);
+ +

If you instead pass an array of functions as the first argument, the results will be an array (the array order results will match the original order that the functions were declared—not the order in which they completed).

+ +

Operações assíncronas em série

+ +

The method async.series() is used to run multiple asynchronous operations in sequence, when subsequent functions do not depend on the output of earlier functions. It is essentially declared and behaves in the same way as async.parallel().

+ +
async.series({
+  one: function(callback) { ... },
+  two: function(callback) { ... },
+  ...
+  something_else: function(callback) { ... }
+  },
+  // optional callback after the last asynchronous function completes.
+  function(err, results) {
+    // 'results' is now equals to: {one: 1, two: 2, ..., something_else: some_value} 
+  }
+);
+ +
+

Note: The ECMAScript (JavaScript) language specification states that the order of enumeration of an object is undefined, so it is possible that the functions will not be called in the same order as you specify them on all platforms. If the order really is important, then you should pass an array instead of an object, as shown below.

+
+ +
async.series([
+  function(callback) {
+    // do some stuff ...
+    callback(null, 'one');
+  },
+  function(callback) {
+    // do some more stuff ... 
+    callback(null, 'two');
+  }
+ ],
+  // optional callback
+  function(err, results) {
+  // results is now equal to ['one', 'two'] 
+  }
+);
+ +

Operações assíncronas dependentes em série

+ +

The method async.waterfall() is used to run multiple asynchronous operations in sequence when each operation is dependent on the result of the previous operation.

+ +

The callback invoked by each asynchronous function contains null for the first argument and results in subsequent arguments. Each function in the series takes the results arguments of the previous callback as the first parameters, and then a callback function. When all operations are complete, a final callback is invoked with the result of the last operation. The way this works is more clear when you consider the code fragment below (this example is from the async documentation):

+ +
async.waterfall([
+  function(callback) {
+    callback(null, 'one', 'two');
+  },
+  function(arg1, arg2, callback) {
+    // arg1 now equals 'one' and arg2 now equals 'two' 
+    callback(null, 'three');
+  },
+  function(arg1, callback) {
+    // arg1 now equals 'three'
+    callback(null, 'done');
+  }
+], function (err, result) {
+  // result now equals 'done'
+}
+);
+ +

Instalando o async

+ +

Install the async module using the NPM package manager so that we can use it in our code. You do this in the usual way, by opening a prompt in the root of the LocalLibrary project and enter the following command:

+ +
npm install async
+ +

Next steps

+ + diff --git a/files/pt-br/learn/server-side/express_nodejs/displaying_data/index.html b/files/pt-br/learn/server-side/express_nodejs/displaying_data/index.html new file mode 100644 index 0000000000..732e4e4417 --- /dev/null +++ b/files/pt-br/learn/server-side/express_nodejs/displaying_data/index.html @@ -0,0 +1,87 @@ +--- +title: 'Express Tutorial Part 5: Displaying library data' +slug: Learn/Server-side/Express_Nodejs/Displaying_data +translation_of: Learn/Server-side/Express_Nodejs/Displaying_data +--- +
{{LearnSidebar}}
+ +
{{PreviousMenuNext("Learn/Server-side/Express_Nodejs/routes", "Learn/Server-side/Express_Nodejs/forms", "Learn/Server-side/Express_Nodejs")}}
+ +

We're now ready to add the pages that display the LocalLibrary website books and other data. The pages will include a home page that shows how many records we have of each model type, and list and detail pages for all of our models. Along the way we'll gain practical experience in getting records from the database, and using templates.

+ + + + + + + + + + + + +
Pré-requisitos:Complete previous tutorial topics (including Express Tutorial Part 4: Routes and controllers).
Objetivo:To understand how to use the async module and Pug template language, and how to get data from the URL in our controller functions.
+ +

Overview

+ +

In our previous tutorial articles we defined Mongoose models that we can use to interact with a database and created some initial library records. We then created all the routes needed for the LocalLibrary website, but with "dummy controller" functions (these are skeleton controller functions that just return a "not implemented" message when a page is accessed).

+ +

The next step is to provide proper implementations for the pages that display our library information (we'll look at implementing pages featuring forms to create, update, or delete information in later articles). This includes updating the controller functions to fetch records using our models, and defining templates to display this information to users.

+ +

We will start by providing overview/primer topics explaining how to manage asynchronous operations in controller functions and how to write templates using Pug. Then we'll provide implementations for each of our main "read only" pages with a brief explanation of any special or new features that they use.

+ +

At the end of this article you should have a good end-to-end understanding of how routes, asynchronous functions, views, and models work in practice.

+ +

Displaying library data tutorial subarticles

+ +

The following subarticles go through the process of adding the different features required for us to display the required website pages. You need to read and work through each one of these in turn, before moving on to the next one.

+ +
    +
  1. Asynchronous flow control using async
  2. +
  3. Template primer
  4. +
  5. The LocalLibrary base template
  6. +
  7. Home page
  8. +
  9. Book list page
  10. +
  11. BookInstance list page
  12. +
  13. Date formatting using moment
  14. +
  15. Author list page and Genre list page challenge
  16. +
  17. Genre detail page
  18. +
  19. Book detail page
  20. +
  21. Author detail page
  22. +
  23. BookInstance detail page and challenge
  24. +
+ +

Summary

+ +

We've now created all the "read-only" pages for our site: a home page that displays counts of instances of each of our models, and list and detail pages for our books, book instances, authors, and genres. Along the way we've gained a lot of fundamental knowledge about controllers, managing flow control when using asynchronous operations, creating views using Pug, querying the database using our models, how to pass information to a template from your view, and how to create and extend templates. Those who completed the challenge will also have learned a little about date handling using moment.

+ +

In our next article we'll build on our knowledge, creating HTML forms and form handling code to start modifying the data stored by the site.

+ +

Veja mais

+ + + +

{{PreviousMenuNext("Learn/Server-side/Express_Nodejs/routes", "Learn/Server-side/Express_Nodejs/forms", "Learn/Server-side/Express_Nodejs")}}

+ +

 

+ +

Neste módulo

+ + + +

 

diff --git a/files/pt-br/learn/server-side/express_nodejs/index.html b/files/pt-br/learn/server-side/express_nodejs/index.html new file mode 100644 index 0000000000..a94962ad4d --- /dev/null +++ b/files/pt-br/learn/server-side/express_nodejs/index.html @@ -0,0 +1,65 @@ +--- +title: Express Web Framework (Node.js/JavaScript) +slug: Learn/Server-side/Express_Nodejs +translation_of: Learn/Server-side/Express_Nodejs +--- +
{{LearnSidebar}}
+ +

Express é um popular framework web estruturado, escrito em JavaScript que roda sobre o ambiente node.js em tempo de execução. Este módulo explica alguns dos principais benefícios deste framework, como configurar o seu ambiente de desenvolvimento e como executar tarefas comuns de desenvolvimento e implantação da web.

+ +

Pré-requisitos

+ +

Antes de iniciar este módulo, você precisará entender o que é programação web e as estruturas do lado do servidor são, o ideal é ler os tópicos em nosso Módulo de primeiros passos da programação de sites do lado servidor. Um conhecimento geral de conceitos de programação e JavaScript é altamente recomendado, mas não é essencial para a compreensão dos conceitos fundamentais.

+ +
+

Nota: Nota: Este site possui muitos recursos úteis para aprender JavaScript no contexto do desenvolvimento do lado do cliente: JavaScript, Guia de JavaScript, princípios básicos de JavaScript, JavaScript (aprendizagem). O core JavaScript linguagem e conceitos são os mesmos para o desenvolvimento do lado do servidor no Node.js e este material será relevante. O Node.js oferece APIs adicionais para suportar funcionalidades que são úteis em ambientes sem navegador, e. Para criar servidores HTTP e acessar o sistema de arquivos, mas não suporta APIs JavaScript para trabalhar com o navegador e o DOM.

+ +

Este guia fornecerá algumas informações sobre como trabalhar com o Node.js e o Express, e existem inúmeros outros recursos excelentes na Internet e em livros - alguns desses relacionados de Como faço para começar com Node.js (StackOverflow) e O que são os Melhores recursos para aprender Node.js? (Quora).

+
+ +

Tutoriais

+ +
+
Express/Node introdução
+
Neste primeiro artigo Express, respondemos as perguntas "O que é Node?" E "O que é Express?" E dar-lhe uma visão geral do que torna a estrutura web Express especial. Apresentaremos os principais recursos e mostraremos alguns dos principais blocos de construção de um aplicativo Express (embora neste momento você ainda não tenha um ambiente de desenvolvimento para testá-lo).
+
Configurando um ambiente de desenvolvimento em Node (Express) 
+
Agora que você sabe o que o Express é, vamos mostrar-lhe como configurar e testar um ambiente de desenvolvimento de Node.js / Express no Windows, Linux (Ubuntu) e Mac OS X. Qualquer sistema operacional comum que você esteja usando, este artigo deve Dê o que você precisa para começar a desenvolver aplicativos Express.
+
Tutorial Express: O site da Biblioteca Local
+
O primeiro artigo da nossa série de tutoriais práticos explica o que você aprenderá e fornecer uma visão geral do exemplo de site da "biblioteca local", no qual estaremos trabalhando e evoluindo em artigos subsquentes.
+
+
Express Tutorial Part 2: Creating a skeleton website
+
Este artigo mostra como você pode criar um projeto de "esqueleto" de website, no qual você pode popular com as rotas específicas do site, modelos/vizualizações e bancos de dados.
+
Express Tutorial Part 3: Using a Database (with Mongoose)
+
This article briefly introduces databases for Node/Express. It then goes on to show how we can use Mongoose to provide database access for the LocalLibrary website. It explains how object schema and models are declared, the main field types, and basic validation. It also briefly shows a few of the main ways you can access model data.
+
Express Tutorial Part 4: Routes and controllers
+
In this tutorial we'll set up routes (URL handling code) with "dummy" handler functions for all the resource endpoints that we'll eventually need in the LocalLibrary website. On completion, we'll have a modular structure for our route handling code, that we can extend with real handler functions in the following articles. We'll also have a really good understanding of how to create modular routes using Express.
+
Express Tutorial Part 5: Displaying library data
+
We're now ready to add the pages that display the LocalLibrary website books and other data. The pages will include a home page that shows how many records we have of each model type, and list and detail pages for all of our models. Along the way we'll gain practical experience in getting records from the database, and using templates.
+
Express Tutorial Part 6: Working with forms
+
In this tutorial we'll show you how to work with HTML Forms in Express, using Pug, and in particular how to write forms to create, update, and delete documents from the database.
+
Express Tutorial Part 7: Deploying to production
+
Now you've created an awesome LocalLibrary website, you're going to want to install it on a public web server so that it can be accessed by library staff and members over the Internet. This article provides an overview of how you might go about finding a host to deploy your website, and what you need to do in order to get your site ready for production.
+
+ +

See also

+ +
+
Installing LocalLibrary on PWS/Cloud Foundry
+
This article provides a practical demonstration of how to install LocalLibrary on the Pivotal Web Services PaaS cloud — this is a full-featured, open source alternative to Heroku, the PaaS cloud service used in Part 7 of the tutorial, listed above. PWS/Cloud Foundry is definitely worth checking out if you are looking for an alternative to Heroku (or another PaaS cloud service), or simply feel like trying something different.
+
+ +

Adding more tutorials

+ +
+

That's the end of the tutorial articles (for now). If you would like to extend it, other interesting topics to cover are:

+ + + +

And of course it would be excellent to have an assessment task!

+
diff --git "a/files/pt-br/learn/server-side/express_nodejs/introdu\303\247\303\243o/index.html" "b/files/pt-br/learn/server-side/express_nodejs/introdu\303\247\303\243o/index.html" new file mode 100644 index 0000000000..15ccfc6145 --- /dev/null +++ "b/files/pt-br/learn/server-side/express_nodejs/introdu\303\247\303\243o/index.html" @@ -0,0 +1,519 @@ +--- +title: Introdução Express/Node +slug: Learn/Server-side/Express_Nodejs/Introdução +tags: + - Aprender + - Express + - Iniciante + - JavaScript + - Node + - Servidor + - Tutorial + - nodejs +translation_of: Learn/Server-side/Express_Nodejs/Introduction +--- +
{{LearnSidebar}}
+ +
{{NextMenu("Learn/Server-side/Express_Nodejs/development_environment", "Learn/Server-side/Express_Nodejs")}}
+ +

Neste primeiro artigo sobre Express responderemos as questões " O que é Node?" e "O que é Express?", além de dar a você uma visão geral sobre o que torna o Express um framework web tão especial. Vamos descrever as principais características e mostrar alguns dos principais blocos de códigos de construção de um aplicativo Express (embora neste momento você ainda não tenha um ambiente de desenvolvimento para testá-lo).

+ + + + + + + + + + + + +
Pré-requisitos:Conhecimentos básicos em informática. Uma compreensão geral de programação web no lado servidor (backend), em particular, nos mecanismos de interação cliente-servidor de websites.
Objetivos:Familiarizar-se com Express, como este framework trabalha junto ao Node, quais as funcionalidades que fornece e quais são os principais blocos de construção de um aplicativo Express.
+ +

O que é Express e Node ?

+ +

Node (ou formalmente Node.js) é um ambiente em tempo de execução open-source (código aberto) e multiplataforma que permite aos desenvolvedores criarem todo tipo de aplicativos e ferramentas do lado servidor (backend) em JavaScript.  Node é usado fora do contexto de um navegador (ou seja executado diretamente no computador ou no servidor). Como tal, o ambiente omite APIs JavaScript específicas do navegador e adiciona suporte para APIs de sistema operacional mais tradicionais, incluindo bibliotecas de sistemas HTTP e arquivos.

+ +

Do ponto de vista do desenvolvimento de um servidor web, o Node possui vários benefícios:

+ + + +

Você pode utilizar o Node.js para criar um simples servidor web, utilizando o pacote Node HTTP.

+ +

Olá, Node.js

+ +

O exemplo a seguir cria um servidor web que escuta qualquer tipo de requisição HTTP na URL  http://127.0.0.1:8000/  --  quando uma requisição é recebida, o script vai responder com a string (texto) "Olá Mundo". Se você já instalou o Node, você pode seguir os passos seguintes deste exemplo.

+ +
    +
  1. Abre o Terminal (no Windows, abra o prompt da linha de comando)
  2. +
  3. Crie uma pasta onde você quer salvar o programa, por exemplo, test-node. Então, entre na pasta com o seguinte comando no terminal:
  4. +
+ +
cd test-node
+
+ +

Use o seu editor de texto preferido, crie um arquivo chamado hello.js e cole o código a seguir:

+ +
// Carrega o modulo HTTP do Node
+var http = require("http");
+
+// Cria um servidor HTTP e uma escuta de requisições para a porta 8000
+http.createServer(function(request, response) {
+
+  // Configura o cabeçalho da resposta com um status HTTP e um Tipo de Conteúdo
+   response.writeHead(200, {'Content-Type': 'text/plain'});
+
+   // Manda o corpo da resposta "Olá Mundo"
+   response.end('Olá Mundo\n');
+}).listen(8000, '127.0.0.1');
+
+// Imprime no console a URL de acesso ao servidor
+console.log('Servidor executando em http://127.0.0.1:8000/');
+ +

Salve o arquivo na pasta que você criou acima.

+ +

Por último, vá para o terminal e digite o comando a seguir:

+ +

node hello.js

+ +

Enfim, abra o browser e digite  http://localhost:8000. Você verá o texto "Olá, Mundo", no canto superior esquerdo.

+ +

Web Frameworks

+ +

Algumas tarefas comuns no desenvolvimento web não são suportadas diretamente pelo Node. Se você quiser que a sua aplicação possua diferentes verbos HTTP (por exemplo GET, POST, DELETE, etc), que gerencie requisições de diferentes URLs ("rotas"), apresente arquivos estáticos ou utilize templates para mostrar as respostas (response) de maneira dinâmica, você não terá muita praticidade usando apenas o Node. Você terá duas opções. Escrever o código por conta própria ou então evitar todo esse trabalho de reinventar a roda ao utilizar um framework.

+ +

Introduzindo o Express

+ +

Express é o framework Node mais popular e a biblioteca subjacente para uma série de outros frameworks do Node. O Express oferece soluções para:

+ + + +

O Express é bastante minimalista, no entanto, os desenvolvedores têm liberdade para criar pacotes de middleware específicos com o objetivo de resolver problemas específicos que surgem no desenvolvimento de uma aplicação. Há bibliotecas para trabalhar com cookies, sessões, login de usuários, parâmetros de URL, dados em requisições POST, cabeçalho de segurança e tantos outros. Você pode achar uma lista de pacotes de middleware mantidos pela equipe Express em Express Middleware (juntamente com uma lista de pacotes populares desenvolvidos por terceiros).

+ +
+

Nota: Essa flexibilidade do Express é uma espada de dois gumes. Há pacotes de middleware para resolver quase qualquer problema ou requisito ao longo do desenvolvimento, mas utilizar os pacotes corretos para cada situação às vezes se torna um grande desafio. Não há "caminho certo" para estruturar um aplicativo. Muitos exemplos que você encontra na Internet não são bons ou mostram apenas uma pequena parte do que você precisa fazer para desenvolver uma aplicação web.

+
+ +

De onde o Node e o Express vieram?

+ +

Node foi inicialmente lançado em 2009, mas naquela época apenas para Linux. O gerenciador de pacotes NPM veio no ano seguinte, 2010, e o suporte nativo do Windows chegou em 2012. A versão atual do Long Term Support (LTS) é o Node v8.9.3, enquanto a versão mais recente é o Node 9. Esse é um resumo da rica histórica do Node, mas é possível conhecer mais na Wikipédia.

+ +

O Express foi lançado em novembro de 2010 e atualmente está na versão 4.16 da API. Você pode verificar o changelog para obter informações sobre as mudanças na versão atual e o GitHub para obter notas detalhadas das versões históricas.

+ + + +

É importante considerar a popularidade de um framework web porque indica se a ferramenta continuará sendo mantida e atualizada, além de apontar quais recursos provavelmente estarão disponíveis na documentação, nas bibliotecas de complemento e no suporte técnico.

+ +

Não há nenhum número capaz de medir precisamente a popularidade de um framework (apesar de que alguns sites como o Hot Frameworks avaliarem a popularidade a partir do número de projetos do GitHub e do número de perguntas do StackOverflow relativas a cada tecnologia). Diante dessa limitação, o mais importante é fazermos algumas outras perguntas para saber se o Node e o Express são "suficientemente populares" para não caírem nos problemas clássicos das tecnologias com pouca adesão da comunidade.

+ +

O Node e o Express continuam a evoluir ? Você pode obter ajuda na comunidade caso precise? Existe uma oportunidade para você receber trabalho remunerado ao dominar o Node e o Express ?

+ +

Baseado no número de empresas de alto perfil que usam Express, no número de pessoas contribuindo para o código base, e no número de pessoas que oferecem suporte (gratuito ou pago), a reposta é sim. O Node e o Express são tecnologias populares!

+ +

Express é opinativo ?

+ +

Os frameworks web costumam se autodeclararem "opinativos" ou "não opinativos".

+ +

Os frameworks opinativos são aqueles com "opiniões" sobre o "caminho certo" para lidar com qualquer tarefa específica. Muitas vezes, apoiam o desenvolvimento rápido em um domínio particular (resolvendo problemas de um tipo específico) porque a maneira correta de fazer qualquer coisa geralmente é bem compreendida e bem documentada. No entanto, são menos flexíveis na resolução de problemas fora de seu domínio principal e tendem a oferecer menos opções para quais componentes e abordagens podem usar nesses casos.

+ +

Frameworks não opinativos, por outro lado, têm muito menos restrições sobre a melhor maneira de utilizar componentes para atingir um objetivo, ou mesmo quais componentes devem ser usados. Eles tornam mais fácil para os desenvolvedores usar as ferramentas mais adequadas para completar uma tarefa específica, embora você precise encontrar esses componentes por si próprio.

+ +

Express é um framework não opinativo. Você pode inserir qualquer middleware que você goste no manuseio das solicitações em quase qualquer ordem que desejar. Pode estruturar o aplicativo em um arquivo ou em vários, usar qualquer estrutura de pastas dentro do diretório principal, etc.

+ +

Como se parece o código do Express ?

+ +

Em um site tradicional baseado em dados, um aplicativo da Web aguarda pedidos HTTP do navegador da web (ou outro cliente). Quando um pedido é recebido, o aplicativo descreve quais ações são necessárias com base no padrão de URL e possivelmente informações associadas contidas em dados POST ou GET. Dependendo do que é necessário, pode-se ler ou escrever informações em um banco de dados ou executar outras tarefas necessárias para satisfazer a solicitação. O aplicativo retornará uma resposta ao navegador da Web, criando, de forma dinâmica, uma página HTML para o navegador, exibindo e inserindo os dados recuperados em espaços reservados em um modelo HTML.

+ +

Express fornece métodos para especificar qual função é chamada quando chega requisição HTTP (GET, POST, SET, etc.) e de rotas e métodos para especificar o mecanismo de modelo ("view") usado, onde o modelo arquivos estão localizados e qual modelo usar para renderizar uma resposta. Você pode usar o middleware Express para adicionar suporte para cookies, sessões e usuários, obtendo parâmetros POST / GET, etc. Você pode usar qualquer mecanismo de banco de dados suportado por Node (o Express não define nenhum comportamento relacionado a banco de dados).

+ +

As seções a seguir explicam algumas das coisas comuns que você verá ao trabalhar com o código Express e Node.

+ +

Olá Mundo Express

+ +

Primeiro, considere o padrão do exemplo do Express Olá Mundo (discutiremos cada trecho do código nas seções abaixo e nas seções a seguir).

+ +
+

Dica: Se você tiver o Node e o Express já instalados (ou se você os instalar como mostrado no próximo artigo, você pode salvar este código em um arquivo chamado app.js e executá-lo em um prompt, ao digitar o comando node app.js.

+
+ +
var express = require('express');
+var app = express();
+
+app.get('/', function(req, res) {
+  res.send('Olá Mundo!');
+});
+
+app.listen(3000, function() {
+  console.log('App de Exemplo escutando na porta 3000!');
+});
+
+ +

As duas primeiras linhas require() importam o módulo Express e criam uma aplicação Express. Esse objeto (tradicionalmente nomeado de app), tem métodos de roteamento de requisições HTTP, configurações de middleware, renderização de views HTML, registro de engines de templates e modificação das configurações que controlam como o aplicativo se comporta (por exemplo, o modo de ambiente, se as definições de rota são sensíveis a maiúsculas e minúsculas, etc).

+ +

A parte do meio do código (as três linhas que começam com app.get) mostra uma definição de rota. O método app.get() especifica uma função de retorno de chamada que será invocada sempre que exista uma solicitação HTTP GET com um caminho ('/') relativo à raiz do site. A função de retorno de chamada requer uma solicitação e um objeto de resposta como argumentos, e simplesmente chama send() na resposta para retornar a string "Olá Mundo!"

+ +

O bloco final inicia o servidor na porta '3000' e imprime um comentário de log no console. Com o servidor em execução, você pode acessar o localhost:3000 em seu navegador para ver o exemplo de resposta retornado.

+ +

Importando e criando módulos

+ +

Um módulo é uma biblioteca/arquivo de JavaScript que você pode importar para outro código usando a função require() do Node. Express por si é um módulo, assim como as bibliotecas de middleware e banco de dados que usamos em nossos aplicativos Express.

+ +

O código abaixo mostra como importamos um módulo por nome, usando o quadro Express como um exemplo. Primeiro invocamos a função require(), especificando o nome do módulo como uma string ('express'), e chamando o objeto retornado para criar um aplicativo Express. Podemos então acessar as propriedades e funções do objeto da aplicação.

+ +
var express = require('express');
+var app = express();
+
+ +

Você também pode criar seus próprios módulos para serem importados da mesma maneira.

+ +
+

Dica: Você vai querer criar seus próprios módulos porque isso permite que você organize seu código em peças gerenciáveis - um aplicativo monolítico (de arquivo único) é difícil de entender e manter. O uso de módulos também ajuda você a gerenciar o namespace, pois somente as variáveis que você exporta explicitamente são importadas quando você usa um módulo.

+
+ +

Para tornar os objetos disponíveis fora do módulo, você precisa apenas atribuí-los ao objeto exports. Por Exemplo, o módulo square.js abaixo é um arquivo que exporta os métodos area() e perimeter():

+ +
exports.area = function(width) { return width * width; };
+exports.perimeter = function(width) { return 4 * width; };
+
+ +

Nós podemos importar este módulo usando require(). Depois, conecte ao(s) método(s) exportado(s) como mostrado a seguir:

+ +
var square = require('./square'); // Chamamos o arquivo utilizando o require()
+console.log('The area of a square with a width of 4 is ' + square.area(4));
+ +
+

Nota: Você também pode especificar um caminho absoluto para o módulo (ou um nome, como fizemos inicialmente).

+
+ +

Se você deseja exportar um objeto completo em uma atribuição, em vez de criar uma propriedade de cada vez, atribua ao module.exports como mostrado abaixo (você também pode fazer isso para tornar a raiz do objeto exporter um construtor ou outra função):

+ +
module.exports = {
+  area: function(width) {
+    return width * width;
+  },
+
+  perimeter: function(width) {
+    return 4 * width;
+  }
+};
+
+ +

Para muitas outras informações sobre módulos veja Módulos (Node API docs).

+ +

Usando APIs assíncronas

+ +

O código JavaScript frequentemente usa APIs assíncronas em vez de síncronas para operações que podem levar algum tempo para serem concluídas. Uma API síncrona é aquela em que cada operação deve ser concluída antes que a próxima operação seja iniciada. Por exemplo, as seguintes funções de log são síncronas e imprimirão o texto no console em ordem (Primeiro, Segundo).

+ +
console.log('Primeiro');
+console.log('Segundo');
+ +
+
Em contrapartida, uma API assíncrona é aquela em que a API iniciará uma operação e retornará imediatamente (antes da conclusão da operação). Assim que a operação terminar, a API usará algum mecanismo para executar operações adicionais. Por exemplo, o código abaixo imprimirá "Segundo, Primeiro". Isso porque, mesmo que o método setTimeout() seja chamado primeiro e retornae imediatamente, a operação precisa de três segundos para finalizar.
+ +
+
+ +
setTimeout(function() {
+   console.log('Primeiro');
+   }, 3000);
+console.log('Segundo');
+
+ +

O uso de APIs assíncronas não bloqueadoras é ainda mais importante no Node do que no navegador, pois o Node é um ambiente de execução orientado por evento único (single threaded). "Single threaded" significa que todos os pedidos para o servidor são executados no mesmo tópico (em vez de serem gerados em processos separados). Esse modelo é extremamente eficiente em termos de velocidade e recursos do servidor, mas isso significa que, se qualquer uma das suas funções chamar métodos síncronos que demoram muito para completar, eles bloquearão não apenas a solicitação atual, mas todas as outras solicitações serão tratadas por sua aplicação web.

+ +

Há várias maneiras de uma API assíncrona notificar para a aplicação que alguma função chegou ao fim. A maneira mais comum é registrar uma função de retorno de chamada quando você invoca a API assíncrona, que será chamada de volta quando a operação for concluída. Usamos essa abordagem acima.

+ +
+

Dica: O uso de callbacks pode ser bastante "bagunçado" se você tiver uma sequência de operações assíncronas dependentes que devem ser executadas em ordem, porque isto resulta em multiplo níveis de callbacks aninhados. Este problema é comumente conhecido como "inferno de callback" ou "código hadouken". Pode-se reduzir o problema ao adotar boas práticas de programação (veja http://callbackhell.com/), utilizar um módulo como async, ou mesmo adotar recursos do ES6, como Promises.

+
+ +
+

Dica: Uma convenção comum para Node e Express é usar as devoluções de retorno de erro. Nesta convenção, o primeiro valor em suas funções de retorno de chamada é um valor de erro, enquanto os argumentos subseqüentes contêm dados de sucesso. Há uma boa explicação de por que essa abordagem é útil neste blog: The Node.js Way - Understanding Error-First Callbacks (fredkschott.com).

+
+ +

Criando manipuladores de rotas

+ +

No nosso Olá Mundo em Express (veja acima), nós definimos uma (callback) função manipuladora de rota para requisição GET HTTP para a raiz do site ('/').

+ +
app.get('/', function(req, res) {
+  res.send('Olá Mundo');
+});
+
+ +

A função de retorno de chamada requer uma solicitação e um objeto de resposta como argumento. Neste caso, o método simplesmente chama send() na resposta para retornar a string "Olá Mundo!" Há uma série de outros métodos de resposta para encerrar o ciclo de solicitação / resposta, por exemplo, você poderia chamar res.json() para enviar uma resposta JSON ou res.sendFile() para enviar um arquivo.

+ +
+

Dica JavaScript: Você pode usar qualquer argumento que você gosta nas funções de retorno de chamada. Quando o retorno de chamada é invocado, o primeiro argumento sempre será o pedido e o segundo sempre será a resposta. Faz sentido nomeá-los de tal forma que você possa identificar o objeto que você está trabalhando no corpo do retorno de chamada.

+
+ +

O Express também fornece métodos para definir manipuladores de rotas para todas as outras requisições HTTP, que são usadas exatamente da mesma maneira: post(), put(), delete(), options(), trace(), copy(), lock(), mkcol(), move(), purge(), propfind(), proppatch(), unlock(), report(), mkactivity(), checkout(), merge(), m-search(), notify(), subscribe(), unsubscribe(), patch(), search(), e connect().

+ +

Há um método de roteamento especial, app.all(), que será chamado em resposta a qualquer método HTTP. É usado para carregar funções de middleware em um caminho específico para todos os métodos de solicitação. O exemplo a seguir (da documentação Express) mostra um manipulador que será executado para solicitações /secret, independentemente do verbo HTTP usado (desde que seja suportado pelo módulo http).

+ +
app.all('/secret', function(req, res, next) {
+  console.log('Acessando a sessão secreta...');
+  next(); // passa o controle para o próximo manipulador
+});
+ +

As rotas permitem combinar padrões de caracteres específicos em um URL e extrair alguns valores do URL e passá-los como parâmetros para o manipulador de rotas (como atributos do objeto de solicitação passado como parâmetro).

+ +

Muitas vezes, é útil agrupar manipuladores de rotas para uma determinada parte de um site e acessá-los usando um prefixo de rota comum (por exemplo, um site com um Wiki pode ter todas as rotas relacionadas ao wiki em um arquivo e tê-los acessado com um prefixo de rota de / wiki /). Em Express, isso é alcançado usando o objeto express.Router. Por exemplo, podemos criar nossa rota wiki em um módulo chamado wiki.js e, em seguida, exportar o objeto Router, conforme mostrado abaixo:

+ +
// wiki.js - Rotas de Wiki
+
+var express = require('express');
+var router = express.Router();
+
+// Home page route
+router.get('/', function(req, res) {
+  res.send('Wiki home page');
+});
+
+// About page route
+router.get('/about', function(req, res) {
+  res.send('About this wiki');
+});
+
+module.exports = router;
+
+ +
+

Nota: Adicionar rotas ao objeto Router é como adicionar rotas ao objeto app (como mostrado anteriormente).

+
+ +

Para usar o roteador em nosso arquivo de aplicativo principal, então, require() o módulo de rota (wiki.js) e depois use() no aplicativo Express para adicionar o Router ao caminho de gerenciamento de middleware. As duas rotas serão acessíveis a partir de /wiki/ e /wiki/about/.

+ +
var wiki = require('./wiki.js');
+// ...
+app.use('/wiki', wiki);
+ +

Vamos mostrar-lhe muito mais sobre trabalhar com rotas e, em particular, sobre o uso do Router, mais tarde, na seção vinculada Rotas e controladores.

+ +

Usando middleware

+ +

O Middleware é usado extensivamente em aplicativos Express para que as tarefas ofereçam arquivos estáticos ao tratamento de erros, a comprensão de respostas HTTP. Enquanto as funções de rota terminam o ciclo de solicitação-resposta HTTP, retornando alguma resposta ao cliente HTTP, as funções de middleware normalmente executam alguma operação na solicitação ou resposta e, em seguida, ligue para a próxima função na "pilha", que pode ser mais um middleware ou uma rota manipuladora. A ordem em que o middleware é chamado depende do desenvolvedor do aplicativo.

+ +
+

Nota: O middleware pode executar qualquer operação, executar qualquer código, fazer alterações no objeto de solicitação e resposta, e também pode encerrar o ciclo de solicitação-resposta. Se não terminar o ciclo, ele deve chamar o next() para passar o controle para a próxima função de middleware (ou a solicitação ficará pendurada).

+
+ +

A maioria dos aplicativos usará middleware de terceiros para simplificar tarefas comuns de desenvolvimento web, como trabalhar com cookies, sessões, autenticação de usuários, acessar dados POST e JSON, log, etc. Você pode encontrar uma lista de pacotes de middleware mantidos pela equipe Express (que também inclui outros pacotes populares de terceiros). Outros pacotes Express estão disponíveis no gerenciador de pacotes do NPM.

+ +

Para usar middleware de terceiros, primeiro você precisa instalá-lo em seu aplicativo usando NPM. Por exemplo, para instalar o logger morgan HTTP, você faria isso:

+ +
$ npm install morgan
+
+ +

Você pode então chamar use() no objeto do aplicativo Express para adicionar o middleware à pilha:

+ +
var express = require('express');
+var logger = require('morgan');
+var app = express();
+app.use(logger('dev'));
+...
+ +
+

Nota: O middleware e as funções de roteamento são chamadas na ordem em que são declaradas. Para alguns middleware, a ordem é importante (por exemplo, se o middleware de sessão depende do middleware de cookies, então o manipulador de cookies deve ser adicionado primeiro). É quase sempre o caso em que o middleware é chamado antes de definir rotas, ou seus manipuladores de rotas não terão acesso à funcionalidade adicionada pelo seu middleware.

+
+ +

Você pode escrever suas próprias funções de middleware. É provável que você tenha que fazê-lo (somente para criar código de manipulação de erro). A única diferença entre uma função de middleware e um retorno de chamada de manipulador de rotas é que as funções de middleware têm um terceiro argumento next, que as funções de middleware devem chamar se não completam o ciclo de solicitação (quando a função de middleware é chamada, isso contém a próxima função que deve ser chamado).

+ +

Você pode adicionar uma função de middleware à cadeia de processamento com app.use() ou app.add(), dependendo se você deseja aplicar o middleware a todas as respostas ou a respostas com um verbo HTTP específico (GET, POST, etc. ). Você especifica rotas o mesmo em ambos os casos, embora a rota seja opcional ao chamar app.use().

+ +

O exemplo abaixo mostra como você pode adicionar a função middleware usando ambos os métodos e com/sem rota.

+ +
var express = require('express');
+var app = express();
+
+// Um exemplo de função middleware
+var a_middleware_function = function(req, res, next) {
+  // ... Executa alguma operação
+  next(); // next() Chama o próximo middleware ou função de rotas
+}
+
+// Função adicionada com use() para todas rotas e requisições
+app.use(a_middleware_function);
+
+// Função adicionada com use() para uma rota específica
+app.use('/someroute', a_middleware_function);
+
+// função middleware adicionado para uma rota e requisição específica
+app.get('/', a_middleware_function);
+
+app.listen(3000);
+ +
+

Dica JavaScript: Acima, declaramos a função de middleware separadamente e, em seguida, configuramos como retorno de chamada. Na nossa função anterior do operador de rotas, declaramos a função de retorno de chamada quando foi utilizada. Em JavaScript, ambas abordagens são válidas.

+
+ +

A documentação Express possui uma documentação excelente sobre como usar e escrever o middleware Express.

+ +

Servindo arquivos estáticos

+ +

Você pode usar o middleware express.static para servir arquivos estáticos, incluindo suas imagens, CSS e JavaScript (static() é a única função de middleware que é realmente parte do Express). Por exemplo, você usaria a linha abaixo para exibir imagens, arquivos CSS e arquivos JavaScript de um diretório chamado 'public' no mesmo nível onde você chama o nó:

+ +
app.use(express.static('public'));
+
+ +

Todos os arquivos no diretório público são atendidos adicionando o nome do arquivo (relativo ao diretório "público" base) ao URL base. Então, por exemplo:

+ +
http://localhost:3000/images/dog.jpg
+http://localhost:3000/css/style.css
+http://localhost:3000/js/app.js
+http://localhost:3000/about.html
+
+ +

Você pode chamar static() várias vezes para atender vários diretórios. Se um arquivo não puder ser encontrado por uma função de middleware, ele simplesmente será transmitido ao middleware subsequente (a ordem em que o middleware é chamado é baseada em sua ordem de declaração).

+ +
app.use(express.static('public'));
+app.use(express.static('media'));
+
+ +

Você também pode criar um prefixo virtual para seus URL estáticos, em vez de ter os arquivos adicionados ao URL base. Por exemplo, aqui especificamos um caminho de montagem para que os arquivos sejam carregados com o prefixo "/media":

+ +
app.use('/media', express.static('public'));
+
+ +

Agora, você pode carregar os arquivos que estão no diretório public a partir do prefixo de caminho /media.

+ +
http://localhost:3000/media/images/dog.jpg
+http://localhost:3000/media/video/cat.mp4
+http://localhost:3000/media/cry.mp3
+
+ +

Para obter mais informações, consulte Servindo arquivos estáticos no Express.

+ +

Erros de manipulação

+ +

Os erros são tratados por uma ou mais funções de middleware especiais que possuem quatro argumentos, em vez dos três habituais: (err, req, res, next). Por exemplo:

+ +
app.use(function(err, req, res, next) {
+  console.error(err.stack);
+  res.status(500).send('Something broke!');
+});
+
+ +

Isso pode retornar qualquer conteúdo exigido, mas deve ser chamado depois de todas as outras chamadas app.use() e rotas para que sejam o último middleware no processo de solicitação de pedidos!

+ +

Express vem com um manipulador de erros embutido, que cuida de todos os erros que podem ser encontrados no aplicativo. Essa função de middleware de gerenciamento de erros padrão é adicionada no final da pilha de funções do middleware. Se você passar um erro para next() e você não lidar com isso em um manipulador de erro, ele será tratado pelo manipulador de erros incorporado; o erro será gravado no cliente com o rastreamento da pilha.

+ +
+

Nota: O rastreamento da pilha não está incluído no ambiente de produção. Para executá-lo no modo de produção, você precisa configurar a variável de ambiente NODE_ENV para 'production'.

+
+ +
+

Nota: HTTP404 e outros códigos de status de "erro" não são tratados como erros. Se você quiser lidar com isso, você pode adicionar uma função de middleware para fazê-lo. Para mais informações, consulte as FAQ.

+
+ +

Para obter mais informações, consulte Gerenciamento de erros (Express docs).

+ +

Usando Banco de Dados

+ +

Aplicativos Express podem usar qualquer mecanismo de banco de dados suportado pelo Node (o Express em si não define nenhum comportamento/requisitos adicionais específicos para gerenciamento de banco de dados). Existem muitas opções, incluindo PostgreSQL, MySQL, Redis, SQLite, MongoDB, etc.

+ +

Para usá-los, você deve primeiro instalar o driver do banco de dados usando NPM. Por exemplo, para instalar o driver para o popular NoSQL MongoDB você usaria o comando:

+ +
$ npm install mongodb
+
+ +

O próprio banco de dados pode ser instalado localmente ou em um servidor em nuvem. No seu código Express, você precisa do driver, conecte-se ao banco de dados e execute as operações criar, ler, atualizar e excluir (CRUD). O exemplo abaixo (da documentação Express) mostra como você pode encontrar registros de "mamíferos" usando MongoDB.

+ +
var MongoClient = require('mongodb').MongoClient;
+
+MongoClient.connect('mongodb://localhost:27017/animals', function(err, db) {
+  if (err) throw err;
+
+  db.collection('mammals').find().toArray(function (err, result) {
+    if (err) throw err;
+
+    console.log(result);
+  });
+});
+ +

Outra abordagem popular é acessar seu banco de dados indiretamente, através de um Object Relational Mapper ("ORM"). Nesta abordagem, você define seus dados como "objetos" ou "modelos" e o ORM mapeia estes para o formato de banco de dados subjacente. Esta abordagem tem o benefício de que, como desenvolvedor, você pode continuar a pensar em termos de objetos JavaScript, em vez de semântica de banco de dados, e que existe um local óbvio para realizar a validação e verificação de dados recebidos. Falaremos mais sobre bancos de dados em um artigo posterior.

+ +

Para obter mais informações, consulte integração com banco de dados (documentos express).

+ +

Renderizando dados (views)

+ +

Os mecanismos de modelo (referidos como "view engines" por Express) permitem que você especifique a estrutura de um documento de saída em um modelo, usando marcadores de posição para os dados que serão preenchidos quando uma página for gerada. Os modelos geralmente são usados para criar HTML, mas também podem criar outros tipos de documentos. Express tem suporte para uma série de mecanismos de modelos, e há uma comparação útil dos motores mais populares aqui: Comparing JavaScript Templating Engines: Jade, Mustache, Dust and More.

+ +

No seu código de configurações do aplicativo você configurou o mecanismo do modelo para usar e o local onde Express deve procurar modelos usando as configurações 'visualizações' e 'visualizar mecanismos', conforme mostrado abaixo (você também terá que instalar o pacote que contém a biblioteca do modelo também !)

+ +
var express = require('express');
+var app = express();
+
+//  Definir o diretório para conter os modelos ('views')
+app.set('views', path.join(__dirname, 'views'));
+
+// Definir o motor de visualização para usar, neste caso 'some_template_engine_name'
+app.set('view engine', 'some_template_engine_name');
+
+ +

A aparência do modelo dependerá do mecanismo que você usa. Supondo que você tenha um arquivo de modelo chamado "índice. <Template_extension>" que contenha espaços reservados para variáveis de dados denominadas 'título' e 'mensagem', você chamaria Response.render() em uma função de roteador de rotas para criar e enviar a resposta HTML :

+ +
app.get('/', function(req, res) {
+  res.render('index', { title: 'About dogs', message: 'Dogs rock!' });
+});
+ +

Para obter mais informações, consulte usando motores de modelo com Express (Express docs).

+ +

Estrutura de Arquivos

+ +

Express não faz suposições em termos de estrutura ou quais os componentes que você usa. Rotas, visualizações, arquivos estáticos e outra lógica específica da aplicação podem viver em qualquer número de arquivos com qualquer estrutura de diretório. Embora seja perfeitamente possível ter todo o aplicativo Express em um único arquivo, geralmente faz sentido dividir seu aplicativo em arquivos com base em função (por exemplo, gerenciamento de contas, blogs, fóruns de discussão) e domínio de problema arquitetônico (por exemplo, modelo, exibição ou controlador se você está usando uma arquitetura MVC).

+ +

Em um tópico posterior, usaremos o Express Application Generator, que cria um esqueleto de aplicativo modular que podemos estender facilmente para criar aplicativos da web.

+ + + +

Sumário

+ +

Parabéns, você completou o primeiro passo em sua viagem Express/Node! Agora você deve entender os principais benefícios do Express e Node, e aproximadamente o que as principais partes de um aplicativo Express podem ser (rotas, middleware, tratamento de erros e código de modelo). Por ser um framework não opinativo, o Express permite que você defina a maneira como essas partes e essas bibliotecas são integradas.

+ +

Claro que Express é deliberadamente uma estrutura de aplicativos web muito leve, tanto seu benefício e potencial vem de bibliotecas e recursos de terceiros. Examinaremos essa questão com mais detalhes nos próximos artigos. No artigo a seguir, vamos analisar a criação de um ambiente de desenvolvimento de Node, para que você possa começar a ver algum código Express em ação.

+ +

Veja também

+ + + +
{{NextMenu("Learn/Server-side/Express_Nodejs/development_environment", "Learn/Server-side/Express_Nodejs")}}
+ +

Próximos módulos

+ + diff --git a/files/pt-br/learn/server-side/express_nodejs/mongoose/index.html b/files/pt-br/learn/server-side/express_nodejs/mongoose/index.html new file mode 100644 index 0000000000..8d733ec077 --- /dev/null +++ b/files/pt-br/learn/server-side/express_nodejs/mongoose/index.html @@ -0,0 +1,838 @@ +--- +title: 'Tutorial Express Parte 3: Usando um banco de dados (com Mongoose)' +slug: Learn/Server-side/Express_Nodejs/mongoose +translation_of: Learn/Server-side/Express_Nodejs/mongoose +--- +
{{LearnSidebar}}
+ +
{{PreviousMenuNext("Learn/Server-side/Express_Nodejs/skeleton_website", "Learn/Server-side/Express_Nodejs/routes", "Learn/Server-side/Express_Nodejs")}}
+ +

Este artigo introduz brevemente bancos de dados e como usá-los com aplicativos Node/Express. Depois demonstra como podemos usar o Mongoose para prover acesso ao banco de dados para o website LocalLibrary. Explica como object schema e modelos são declarados, os principais tipos de campos e validações básicas. Também demonstra brevemente algumas das muitas maneiras em que se pode acessar os dados do modelo.

+ + + + + + + + + + + + +
Pré-requisitos:Tutorial Express Parte 2: Criando o esqueleto de um website
Objetivo:Ser capaz de projetar e criar seus próprios modelos usando Mongoose.
+ +

Visão geral

+ +

A equipe da biblioteca usará o site da Biblioteca Local para gardar informações sobre livros e empréstimos, enquanto os membros da biblioteca irão utilizá-lo para navegar e pesquisar por livros, descobrir se há alguma cópia disponível, e então reservar ou emprestar eles. Para armazenar e obter informações eficientemente, nós guardaremos elas em um banco de dados.

+ +

Aplicativos Express podem usar muitos bancos de dados diferentes, e existem várias abordagens que você pode usar para fazer operações de Criar, Ler, Atualizar e Apagar (CRUD, na sigla em inglês). Esse tutorial provê uma curta visão geral de algumas das opções disponíveis e então irá mostrar em detalhes os mecanismos particulares selecionados.

+ +

Quais bancos de dados eu posso usar?

+ +

Aplicativos Express podem usar qualquer banco de dados suportado pelo Node (O Express por si só não define nenhum requerimento ou comportamento adicional específico para gerenciamento de bancos de dados). Há muitas opções populares, incluindo PostgreSQL, MySQL, Redis, SQLite, and MongoDB.

+ +

Quando escolher um banco de dados, você deveria considerar coisas como o tempo-para-produtividade/curva de aprendizado, performance, facilidade de replicação/backup, custo, suporte da comunidade, etc. Enquanto não existe o "melhor" banco de dados, praticamente qualquer uma das soluções populares devem ser mais do que aceitáveis para um site de tamanho pequeno a médio como o da nossa Biblioteca Local.

+ +

Para mais informações sobre as opções veja Integração com o Banco de dados (documentação do Express).

+ +

Qual o melhor jeito de interagir com um banco de dados?

+ +

There are two approaches for interacting with a database: 

+ + + +

The very best performance can be gained by using SQL, or whatever query language is supported by the database. ODM's are often slower because they use translation code to map between objects and the database format, which may not use the most efficient database queries (this is particularly true if the ODM supports different database backends, and must make greater compromises in terms of what database features are supported).

+ +

The benefit of using an ORM is that programmers can continue to think in terms of JavaScript objects rather than database semantics — this is particularly true if you need to work with different databases (on either the same or different websites). They also provide an obvious place to perform validation and checking of data.

+ +
+

Tip:  Using ODM/ORMs often results in lower costs for development and maintenance! Unless you're very familiar with the native query language or performance is paramount, you should strongly consider using an ODM.

+
+ +

Qual ORM/ODM eu devo usar?

+ +

There are many ODM/ORM solutions available on the NPM package manager site (check out the odm and orm tags for a subset!).

+ +

A few solutions that were popular at the time of writing are:

+ + + +

As a general rule, you should consider both the features provided and the "community activity" (downloads, contributions, bug reports, quality of documentation, etc.) when selecting a solution. At the time of writing Mongoose is by far the most popular ODM, and is a reasonable choice if you're using MongoDB for your database.

+ +

Usando Mongoose e MongoDb para a LocalLibrary

+ +

Para o exemplo da Local Library (e para o resto do tópico) nós iremos usar o  Mongoose ODM para acessar os dados da nossa aplicação. Mongoose funciona como uma interface para o MongoDB, um banco de dados de código aberto e NoSQL que usa um modelo de dados orientado a documentos. Uma “coleção” de “documentos”, em uma base de dados do MongoDB, é semelhante a uma “tabela” com “linhas” em uma base dados relacional.

+ +

Esse ODM (Object Data Model) e banco de dados combinados são extremamente populares na comunidade do Node, particularmente porque os documentos armazenados e os métodos de consultas se parecem muito com JSON, que consequentemente são muito familiares aos desenvolvedores JavaScript.

+ +
+

Dica: Você não precisa conhecer o MongoDB antes de usar o Mongoose, apesar de que partes da documentação do Mongoose são mais fáceis de entender se você já está familiarizado com o MongoDB.

+
+ +

O resto desse tutorial mostra como definir e acessar os modelos e schemas no Mongoose para o nosso website da LocalLibrary.

+ +

Projetando os modelos da aplicação LocalLibrary

+ + + +

Antes de pularmos de cabeça na codificação dos modelos, vale a pena pensar uns minutinhos sobre quais dados precisamos armazenar e o relacionamento entre diferentes objetos.

+ +

Nós sabemos que precisamos armazenar informações sobre livros(título, resumo, autor, gênero, ISBN) e que nós podemos ter múltiplas cópias disponíveis (com ids globlamente únicos, status de disponibilidade, etc.). Nós também podemos armazenar mais informações sobre o autor do que apenas seu nome, e podem haver múltiplos autores com o mesmo nome ou um bem parecido. Nós queremos também ser capazes de ordernar informações baseadas no título do livro, autor, gênero e categoria.

+ +

Ao estruturar seus modelos é sempre bom separar modelos para cada "objeto"(um grupo de informações relacionadas). Neste caso, os nossos objetos mais evidentes são os de livros (books), pedidos de livros (book instances), e autores (authors).

+ +

Você pode usar também modelos para representar opções de listagens(por exemplo um menu drop-down com escolhas para o usuário), ao invés de implementar as escolhas diretamente em linhas de códigos dentro do seu website — isso é recomendado quando as escolhas não são conhecidas durante o desenvolvimento ou quando elas podem mudar. O candidato mais evidente para um modelo desse tipo é o de gênero (genre) de livros (por exemplo Ficção Ciêntífica, Poesia Clássica, etc.).

+ +

Uma vez que nós decidimos nossos modelos e os seus atributos, nós precisamos pensar sobre o relacionamento entre eles.

+ +

Com isso em mente, o diagrama UML a seguir mostra os modelos (as caixas) que iremos definir na nossa aplicação. Como discutido acima, criamos modelos para os livros ( com informações genéricas sobre o livro), pedidos de livros(status de cópias físicas de um livro específico disponíveis no sistema), e autor. E também decidimos ter um modelo para o gênero então esses valores poderão ser criados dinamicamente na aplicação. Outra decisão foi de não criarmos um modelo para  BookInstance:status  — nós deixaremos diretamente no código os valores aceitáveis  para o status de pedidos porque nós não esperamos que eles mudem. Dentro de cada caixa, você pode ver o nome do modelo, o nome dos atributos e seus tipos, e também os métodos e seu tipo de retorno.

+ +

O diagrama também mostra o relacionamento entre modelos, incluindo sua cardinalidade. A cardinalidade são os números no diagrama próximos das linhas que conectam as caixas mostrando os números (máximo e mínimo) de cada modelo que pode estar presente no relacionamento. Por exemplo, as linhas que conectam as caixas Booke Genre mostram que as duas coleções têm uma relação. Os números próximos ao modelo Book mostra que Genre pode ter zero ou mais Book (quantos você quiser), enquanto no outro fim da linha de conexão próximo a Genre  mostra que ele pode ter zero ou mais livros associados.

+ +
+

Nota: Assim como discutido abaixo em Iniciando com Mongoose  muitas vezes é melhor ter o atributo que define a relação entre os documentos/modelos em apenas um dos modelos( você ainda pode encontrar o relacionamento reverso pesquisando o _id associado no outro modelo). Abaixo nós escolhemos definir o modelo Book Schema para armazenar o relacionamento entre Book/Genre e Book/Author, e definimos  BookInstance Schema para armazenar o relacionamento entre Book/BookInstance. Esta escolha foi um tanto arbitrária — nós poderíamos igualmente ter declarado esses atributos em outro schema.

+
+ +

Mongoose Library Model  with correct cardinality

+ +
+

Nota: A próxima seção fornece um guia explicando como os modelos são definidos e usados. Ao ler, considere como iremos construir cada um dos modelos no diagrama acima.

+
+ +

Iniciando com Mongoose

+ +

Esta seção fornece uma visão geral de como conectar o Mongoose a um banco de dados do MongoDB, como definir um schema e um modelo, e como fazer consultas básicas.

+ +
+

Nota: Esse guia é "bastante influenciado" pelo conteúdo encontrado no Mongoose quick start do npm e pela documentação oficial.

+
+ +

Instalando Mongoose e MongoDB

+ +

O Mongoose é instalado no seu projeto (package.json) assim como outra dependência qualquer — usando NPM. Para instalá-lo, use a seguinte linha de comando dentro da pasta do seu projeto:

+ +
npm install mongoose
+
+ +

Installing Mongoose adds all its dependencies, including the MongoDB database driver, but it does not install MongoDB itself. If you want to install a MongoDB server then you can download installers from here for various operating systems and install it locally. You can also use cloud-based MongoDB instances.

+ +
+

Note: For this tutorial, we'll be using the MongoDB Atlas cloud-based database as a service free tier to provide the database. This is suitable for development and makes sense for the tutorial because it makes "installation" operating system independent (database-as-a-service is also one approach you might well use for your production database).

+
+ +

Conectando ao MongoDB

+ +

Mongoose requires a connection to a MongoDB database. You can require() and connect to a locally hosted database with mongoose.connect(), as shown below.

+ +
//Import the mongoose module
+var mongoose = require('mongoose');
+
+//Set up default mongoose connection
+var mongoDB = 'mongodb://127.0.0.1/my_database';
+mongoose.connect(mongoDB, { useNewUrlParser: true });
+
+//Get the default connection
+var db = mongoose.connection;
+
+//Bind connection to error event (to get notification of connection errors)
+db.on('error', console.error.bind(console, 'MongoDB connection error:'));
+ +

You can get the default Connection object with mongoose.connection. Once connected, the open event is fired on the Connection instance.

+ +
+

Tip: If you need to create additional connections you can use mongoose.createConnection(). This takes the same form of database URI (with host, database, port, options etc.) as connect() and returns a Connection object).

+
+ +

Definindo e criando modelos

+ +

Models are defined using the Schema interface. The Schema allows you to define the fields stored in each document along with their validation requirements and default values. In addition, you can define static and instance helper methods to make it easier to work with your data types, and also virtual properties that you can use like any other field, but which aren't actually stored in the database (we'll discuss a bit further below).

+ +

Schemas are then "compiled" into models using the mongoose.model() method. Once you have a model you can use it to find, create, update, and delete objects of the given type.

+ +
+

Note: Each model maps to a collection of documents in the MongoDB database. The documents will contain the fields/schema types defined in the model Schema.

+
+ +

Defining schemas

+ +

The code fragment below shows how you might define a simple schema. First you require() mongoose, then use the Schema constructor to create a new schema instance, defining the various fields inside it in the constructor's object parameter.

+ +
//Require Mongoose
+var mongoose = require('mongoose');
+
+//Define a schema
+var Schema = mongoose.Schema;
+
+var SomeModelSchema = new Schema({
+  a_string: String,
+  a_date: Date
+});
+
+ +

In the case above we just have two fields, a string and a date. In the next sections, we will show some of the other field types, validation, and other methods.

+ +

Criando um modelo

+ +

Models are created from schemas using the mongoose.model() method:

+ +
// Define schema
+var Schema = mongoose.Schema;
+
+var SomeModelSchema = new Schema({
+  a_string: String,
+  a_date: Date
+});
+
+// Compile model from schema
+var SomeModel = mongoose.model('SomeModel', SomeModelSchema );
+ +

The first argument is the singular name of the collection that will be created for your model (Mongoose will create the database collection for the above model SomeModel above), and the second argument is the schema you want to use in creating the model.

+ +
+

Note: Once you've defined your model classes you can use them to create, update, or delete records, and run queries to get all records or particular subsets of records. We'll show you how to do this in the Using models section, and when we create our views.

+
+ +

Schema types (fields)

+ +

A schema can have an arbitrary number of fields — each one represents a field in the documents stored in MongoDB. An example schema showing many of the common field types and how they are declared is shown below.

+ +
var schema = new Schema(
+{
+  name: String,
+  binary: Buffer,
+  living: Boolean,
+  updated: { type: Date, default: Date.now() },
+  age: { type: Number, min: 18, max: 65, required: true },
+  mixed: Schema.Types.Mixed,
+  _someId: Schema.Types.ObjectId,
+  array: [],
+  ofString: [String], // You can also have an array of each of the other types too.
+  nested: { stuff: { type: String, lowercase: true, trim: true } }
+})
+ +

Most of the SchemaTypes (the descriptors after “type:” or after field names) are self-explanatory. The exceptions are:

+ + + +

The code also shows both ways of declaring a field:

+ + + +

For more information about options see SchemaTypes (Mongoose docs).

+ +

Validação

+ +

Mongoose provides built-in and custom validators, and synchronous and asynchronous validators. It allows you to specify both the acceptable range or values and the error message for validation failure in all cases.

+ +

The built-in validators include:

+ + + +

The example below (slightly modified from the Mongoose documents) shows how you can specify some of the validator types and error messages:

+ +
var breakfastSchema = new Schema({
+  eggs: {
+    type: Number,
+    min: [6, 'Too few eggs'],
+    max: 12,
+    required: [true, 'Why no eggs?']
+  },
+  drink: {
+    type: String,
+    enum: ['Coffee', 'Tea', 'Water',]
+  }
+});
+
+ +

For complete information on field validation see Validation (Mongoose docs).

+ +

Propriedades virtuais

+ +

Virtual properties are document properties that you can get and set but that do not get persisted to MongoDB. The getters are useful for formatting or combining fields, while setters are useful for de-composing a single value into multiple values for storage. The example in the documentation constructs (and deconstructs) a full name virtual property from a first and last name field, which is easier and cleaner than constructing a full name every time one is used in a template.

+ +
+

Note: We will use a virtual property in the library to define a unique URL for each model record using a path and the record's _id value.

+
+ +

For more information see Virtuals (Mongoose documentation).

+ +

Methods and query helpers

+ +

A schema can also have instance methods, static methods, and query helpers. The instance and static methods are similar, but with the obvious difference that an instance method is associated with a particular record and has access to the current object. Query helpers allow you to extend mongoose's chainable query builder API (for example, allowing you to add a query "byName" in addition to the find(), findOne() and findById() methods).

+ +

Usando modelos

+ +

Once you've created a schema you can use it to create models. The model represents a collection of documents in the database that you can search, while the model's instances represent individual documents that you can save and retrieve.

+ +

We provide a brief overview below. For more information see: Models (Mongoose docs).

+ +

Criando e modificando documentos

+ +

To create a record you can define an instance of the model and then call save(). The examples below assume SomeModel is a model (with a single field "name") that we have created from our schema.

+ +
// Create an instance of model SomeModel
+var awesome_instance = new SomeModel({ name: 'awesome' });
+
+// Save the new model instance, passing a callback
+awesome_instance.save(function (err) {
+  if (err) return handleError(err);
+  // saved!
+});
+
+ +

Creation of records (along with updates, deletes, and queries) are asynchronous operations — you supply a callback that is called when the operation completes. The API uses the error-first argument convention, so the first argument for the callback will always be an error value (or null). If the API returns some result, this will be provided as the second argument.

+ +

You can also use create() to define the model instance at the same time as you save it. The callback will return an error for the first argument and the newly-created model instance for the second argument.

+ +
SomeModel.create({ name: 'also_awesome' }, function (err, awesome_instance) {
+  if (err) return handleError(err);
+  // saved!
+});
+ +

Every model has an associated connection (this will be the default connection when you use mongoose.model()). You create a new connection and call .model() on it to create the documents on a different database.

+ +

You can access the fields in this new record using the dot syntax, and change the values. You have to call save() or update() to store modified values back to the database.

+ +
// Access model field values using dot notation
+console.log(awesome_instance.name); //should log 'also_awesome'
+
+// Change record by modifying the fields, then calling save().
+awesome_instance.name="New cool name";
+awesome_instance.save(function (err) {
+   if (err) return handleError(err); // saved!
+});
+
+ +

Pesquisando por registros

+ +

You can search for records using query methods, specifying the query conditions as a JSON document. The code fragment below shows how you might find all athletes in a database that play tennis, returning just the fields for athlete name and age. Here we just specify one matching field (sport) but you can add more criteria, specify regular expression criteria, or remove the conditions altogether to return all athletes.

+ +
var Athlete = mongoose.model('Athlete', yourSchema);
+
+// find all athletes who play tennis, selecting the 'name' and 'age' fields
+Athlete.find({ 'sport': 'Tennis' }, 'name age', function (err, athletes) {
+  if (err) return handleError(err);
+  // 'athletes' contains the list of athletes that match the criteria.
+})
+ +

If you specify a callback, as shown above, the query will execute immediately. The callback will be invoked when the search completes.

+ +
+

Note: All callbacks in Mongoose use the pattern callback(error, result). If an error occurs executing the query, the error parameter will contain an error document and result will be null. If the query is successful, the error parameter will be null, and the result will be populated with the results of the query.

+
+ +
+

Note: It is important to remember that not finding any results is not an error for a search —but it may be a fail-case in the context of your application. If your application expects a search to find a value you can either check the result in the callback (results==null) or daisy chain the method orFail() on the query. 

+
+ +

If you don't specify a callback then the API will return a variable of type Query. You can use this query object to build up your query and then execute it (with a callback) later using the exec() method.

+ +
// find all athletes that play tennis
+var query = Athlete.find({ 'sport': 'Tennis' });
+
+// selecting the 'name' and 'age' fields
+query.select('name age');
+
+// limit our results to 5 items
+query.limit(5);
+
+// sort by age
+query.sort({ age: -1 });
+
+// execute the query at a later time
+query.exec(function (err, athletes) {
+  if (err) return handleError(err);
+  // athletes contains an ordered list of 5 athletes who play Tennis
+})
+ +

Above we've defined the query conditions in the find() method. We can also do this using a where() function, and we can chain all the parts of our query together using the dot operator (.) rather than adding them separately. The code fragment below is the same as our query above, with an additional condition for the age.

+ +
Athlete.
+  find().
+  where('sport').equals('Tennis').
+  where('age').gt(17).lt(50).  //Additional where query
+  limit(5).
+  sort({ age: -1 }).
+  select('name age').
+  exec(callback); // where callback is the name of our callback function.
+ +

The find() method gets all matching records, but often you just want to get one match. The following methods query for a single record:

+ + + +
+

Note: There is also a count() method that you can use to get the number of items that match conditions. This is useful if you want to perform a count without actually fetching the records.

+
+ +

There is a lot more you can do with queries. For more information see: Queries (Mongoose docs).

+ + + +

You can create references from one document/model instance to another using the ObjectId schema field, or from one document to many using an array of ObjectIds. The field stores the id of the related model. If you need the actual content of the associated document, you can use the populate() method in a query to replace the id with the actual data.

+ +

For example, the following schema defines authors and stories. Each author can have multiple stories, which we represent as an array of ObjectId. Each story can have a single author. The "ref" (highlighted in bold below) tells the schema which model can be assigned to this field.

+ +
var mongoose = require('mongoose')
+  , Schema = mongoose.Schema
+
+var authorSchema = Schema({
+  name    : String,
+  stories : [{ type: Schema.Types.ObjectId, ref: 'Story' }]
+});
+
+var storySchema = Schema({
+  author : { type: Schema.Types.ObjectId, ref: 'Author' },
+  title    : String
+});
+
+var Story  = mongoose.model('Story', storySchema);
+var Author = mongoose.model('Author', authorSchema);
+ +

We can save our references to the related document by assigning the _id value. Below we create an author, then a story, and assign the author id to our stories author field.

+ +
var bob = new Author({ name: 'Bob Smith' });
+
+bob.save(function (err) {
+  if (err) return handleError(err);
+
+  //Bob now exists, so lets create a story
+  var story = new Story({
+    title: "Bob goes sledding",
+    author: bob._id    // assign the _id from the our author Bob. This ID is created by default!
+  });
+
+  story.save(function (err) {
+    if (err) return handleError(err);
+    // Bob now has his story
+  });
+});
+ +

Our story document now has an author referenced by the author document's ID. In order to get the author information in the story results we use populate(), as shown below.

+ +
Story
+.findOne({ title: 'Bob goes sledding' })
+.populate('author') //This populates the author id with actual author information!
+.exec(function (err, story) {
+  if (err) return handleError(err);
+  console.log('The author is %s', story.author.name);
+  // prints "The author is Bob Smith"
+});
+ +
+

Note: Astute readers will have noted that we added an author to our story, but we didn't do anything to add our story to our author's stories array. How then can we get all stories by a particular author? One way would be to add our author to the stories array, but this would result in us having two places where the information relating authors and stories needs to be maintained.

+ +

A better way is to get the _id of our author, then use find() to search for this in the author field across all stories.

+ +
Story
+.find({ author : bob._id })
+.exec(function (err, stories) {
+  if (err) return handleError(err);
+  // returns all stories that have Bob's id as their author.
+});
+
+
+ +

This is almost everything you need to know about working with related items for this tutorial. For more detailed information see Population (Mongoose docs).

+ +

One schema/model per file

+ +

While you can create schemas and models using any file structure you like, we highly recommend defining each model schema in its own module (file), exporting the method to create the model. This is shown below:

+ +
// File: ./models/somemodel.js
+
+//Require Mongoose
+var mongoose = require('mongoose');
+
+//Define a schema
+var Schema = mongoose.Schema;
+
+var SomeModelSchema = new Schema({
+  a_string          : String,
+  a_date            : Date,
+});
+
+//Export function to create "SomeModel" model class
+module.exports = mongoose.model('SomeModel', SomeModelSchema );
+ +

You can then require and use the model immediately in other files. Below we show how you might use it to get all instances of the model.

+ +
//Create a SomeModel model just by requiring the module
+var SomeModel = require('../models/somemodel')
+
+// Use the SomeModel object (model) to find all SomeModel records
+SomeModel.find(callback_function);
+ +

Configurando o banco de dados MongoDB

+ +

Now that we understand something of what Mongoose can do and how we want to design our models, it's time to start work on the LocalLibrary website. The very first thing we want to do is set up a MongoDb database that we can use to store our library data.

+ +

For this tutorial, we're going to use the MongoDB Atlas free cloud-hosted sandbox database. This database tier is not considered suitable for production websites because it has no redundancy, but it is great for development and prototyping. We're using it here because it is free and easy to set up, and because MongoDB Atlas is a popular database as a service vendor that you might reasonably choose for your production database (other popular choices at the time of writing include Compose, ScaleGrid and ObjectRocket).

+ +
+

Note: If you prefer you can set up a MongoDb database locally by downloading and installing the appropriate binaries for your system. The rest of the instructions in this article would be similar, except for the database URL you would specify when connecting.

+
+ +

You will first need to create an account with MongoDB Atlas (this is free, and just requires that you enter basic contact details and acknowledge their terms of service). 

+ +

After logging in, you'll be taken to the home screen:

+ +
    +
  1. Click Buid a Cluster button in the Clusters Overview section.
    + Create a cluster on MongoDB Atlas.
  2. +
  3. This will open the Create New Cluster screen.
    + Choose a cloud provider when using MongoDB Atlas. +
      +
    • Select any provider from the Cloud Provider & Region section. Different providers offer different regions.
    • +
    • Select any region marked "FREE TIER AVAILABLE".
    • +
    • Click the Create Cluster button (creation of the cluster will take some minutes).
    • +
    +
  4. +
  5. +

    You will return to the Cluster Overview screen.
    + Setup a collection on MongoDB Atlas.

    + +
      +
    • +

      Click the Collections button.

      +
    • +
    +
  6. +
  7. This will open the Collections section.
    + Create a database on MongoDB Atlas. +
      +
    • Click the Create Database button.
    • +
    +
  8. +
  9. This will open the Create Database screen.
    + Details during database creation on MongoDB Atlas. +
      +
    • Enter the name for the new database as local_library.
    • +
    • Enter the name of the collection as Collection0.
    • +
    • Click the Create button to create the database.
    • +
    +
  10. +
  11. You will return to the Collection screen with your database created.
    + Database creation confirmation on MongoDB Atlas. +
      +
    • Click the Overview tab to return the cluster overview.
    • +
    +
  12. +
  13. From the Cluster0 Overview screen click the Connect button.
    + Configure a connection when after setting up a cluster in MongoDB Atlas.
  14. +
  15. This will open the Connect to Cluster screen.
    + Setup a connection when using MongoDB Atlas. +
      +
    • Click the Add a Different IP Address button, enter 0.0.0.0/0 for the IP Address and click Add IP Address button. +
      +

      Note: It is a best practice to limit the IP addresses that can connect to your database and other resources. Here we allow a connection from anywhere because we don't know where the request will come from after deployment.

      +
      +
    • +
    • Enter a username and password and click Create MongoDB User button. +
      +

      Note: Avoid using special characters in your MongoDB user password as mongoose may not parse the connection string properly.

      +
      +
    • +
    • If you have completed the 2 previous steps, the button Choose a connection method will turn green.
    • +
    • Click the Choose a connection method button.
    • +
    +
  16. +
  17. This will access the Choose a connection method tab.
    + Choose a connection type when connecting with MongoDB Atlas. +
      +
    • Click the Connect Your Application option.
    • +
    +
  18. +
  19. This will open the Connect screen.
    + Choose the Short SRV connection when settinup a connection on MongoDB Atalas. +
      +
    • Click the Short SRV connection string option to copy the connection string.
    • +
    +
  20. +
  21. This will open the connection string URL.
    + Copy the Short SRV connection string when setting up a connection on MongoDB Atlas +
      +
    • Choose Copy button to copy the string.
    • +
    • Save this string somewhere safe.
    • +
    • Update the password with your users password.
    • +
    • Replace test with local_library.
    • +
    +
  22. +
+ +

You have now created the database, and have an URL (with username and password) that can be used to access it. This will look something like: mongodb+srv://your_user_name:your_password@cluster0-mbdj7.mongodb.net/local_library?retryWrites=true

+ +

Instalando Mongoose

+ +

Open a command prompt and navigate to the directory where you created your skeleton Local Library website. Enter the following command to install Mongoose (and its dependencies) and add it to your package.json file, unless you have already done so when reading the Mongoose Primer above.

+ +
npm install mongoose
+
+ +

Conectando ao MongoDB

+ +

Open /app.js (in the root of your project) and copy the following text below where you declare the Express application object (after the line var app = express();). Replace the database url string ('insert_your_database_url_here') with the location URL representing your own database (i.e. using the information from mongoDB Atlas).

+ +
//Set up mongoose connection
+var mongoose = require('mongoose');
+var mongoDB = 'insert_your_database_url_here';
+mongoose.connect(mongoDB, { useNewUrlParser: true });
+var db = mongoose.connection;
+db.on('error', console.error.bind(console, 'MongoDB connection error:'));
+ +

As discussed in the Mongoose primer above, this code creates the default connection to the database and binds to the error event (so that errors will be printed to the console). 

+ +

Defining the LocalLibrary Schema

+ +

We will define a separate module for each model, as discussed above. Start by creating a folder for our models in the project root (/models) and then create separate files for each of the models:

+ +
/express-locallibrary-tutorial  //the project root
+  /models
+    author.js
+    book.js
+    bookinstance.js
+    genre.js
+
+ +

Author model

+ +

Copy the Author schema code shown below and paste it into your ./models/author.js file. The scheme defines an author has having String SchemaTypes for the first and family names, that are required and have a maximum of 100 characters, and Date fields for the date of birth and death.

+ +
var mongoose = require('mongoose');
+
+var Schema = mongoose.Schema;
+
+var AuthorSchema = new Schema(
+  {
+    first_name: {type: String, required: true, max: 100},
+    family_name: {type: String, required: true, max: 100},
+    date_of_birth: {type: Date},
+    date_of_death: {type: Date},
+  }
+);
+
+// Virtual for author's full name
+AuthorSchema
+.virtual('name')
+.get(function () {
+  return this.family_name + ', ' + this.first_name;
+});
+
+// Virtual for author's lifespan
+AuthorSchema
+.virtual('lifespan')
+.get(function () {
+  return (this.date_of_death.getYear() - this.date_of_birth.getYear()).toString();
+});
+
+// Virtual for author's URL
+AuthorSchema
+.virtual('url')
+.get(function () {
+  return '/catalog/author/' + this._id;
+});
+
+//Export model
+module.exports = mongoose.model('Author', AuthorSchema);
+
+
+ +

We've also declared a virtual for the AuthorSchema named "url" that returns the absolute URL required to get a particular instance of the model — we'll use the property in our templates whenever we need to get a link to a particular author.

+ +
+

Note: Declaring our URLs as a virtual in the schema is a good idea because then the URL for an item only ever needs to be changed in one place.
+ At this point, a link using this URL wouldn't work, because we haven't got any routes handling code for individual model instances. We'll set those up in a later article!

+
+ +

At the end of the module, we export the model.

+ +

Book model

+ +

Copy the Book schema code shown below and paste it into your ./models/book.js file. Most of this is similar to the author model — we've declared a schema with a number of string fields and a virtual for getting the URL of specific book records, and we've exported the model.

+ +
var mongoose = require('mongoose');
+
+var Schema = mongoose.Schema;
+
+var BookSchema = new Schema(
+  {
+    title: {type: String, required: true},
+    author: {type: Schema.Types.ObjectId, ref: 'Author', required: true},
+    summary: {type: String, required: true},
+    isbn: {type: String, required: true},
+    genre: [{type: Schema.Types.ObjectId, ref: 'Genre'}]
+  }
+);
+
+// Virtual for book's URL
+BookSchema
+.virtual('url')
+.get(function () {
+  return '/catalog/book/' + this._id;
+});
+
+//Export model
+module.exports = mongoose.model('Book', BookSchema);
+
+ +

The main difference here is that we've created two references to other models:

+ + + +

BookInstance model

+ +

Finally, copy the BookInstance schema code shown below and paste it into your ./models/bookinstance.js file. The BookInstance represents a specific copy of a book that someone might borrow and includes information about whether the copy is available or on what date it is expected back, "imprint" or version details.

+ +
var mongoose = require('mongoose');
+
+var Schema = mongoose.Schema;
+
+var BookInstanceSchema = new Schema(
+  {
+    book: { type: Schema.Types.ObjectId, ref: 'Book', required: true }, //reference to the associated book
+    imprint: {type: String, required: true},
+    status: {type: String, required: true, enum: ['Available', 'Maintenance', 'Loaned', 'Reserved'], default: 'Maintenance'},
+    due_back: {type: Date, default: Date.now}
+  }
+);
+
+// Virtual for bookinstance's URL
+BookInstanceSchema
+.virtual('url')
+.get(function () {
+  return '/catalog/bookinstance/' + this._id;
+});
+
+//Export model
+module.exports = mongoose.model('BookInstance', BookInstanceSchema);
+ +

The new things we show here are the field options:

+ + + +

Everything else should be familiar from our previous schema.

+ +

Genre model - challenge!

+ +

Open your ./models/genre.js file and create a schema for storing genres (the category of book, e.g. whether it is fiction or non-fiction, romance or military history, etc).

+ +

The definition will be very similar to the other models:

+ + + +

Testando — criando alguns itens

+ +

That's it. We now have all models for the site set up!

+ +

In order to test the models (and to create some example books and other items that we can use in our next articles) we'll now run an independent script to create items of each type:

+ +
    +
  1. Download (or otherwise create) the file populatedb.js inside your express-locallibrary-tutorial directory (in the same level as package.json). + +
    +

    Note: You don't need to know how populatedb.js works; it just adds sample data into the database.

    +
    +
  2. +
  3. Enter the following commands in the project root to install the async module that is required by the script (we'll discuss this in later tutorials, ) +
    npm install async
    +
  4. +
  5. Run the script using node in your command prompt, passing in the URL of your MongoDB database (the same one you replaced the insert_your_database_url_here placeholder with, inside app.js earlier): +
    node populatedb <your mongodb url>​​​​
    + +
    +

    Note for Windows operating system users: If the above command results in the error DeprecationWarning: current URL string parser is deprecated, change the mongoose.connect(mongoDB); line in populatedb.js file with mongoose.connect(mongoDB, { useNewUrlParser:true });

    +
    +
  6. +
  7. The script should run through to completion, displaying items as it creates them in the terminal.
  8. +
+ +
+

Tip: Go to your database on mongoDB Atlas (in the Collections tab). You should now be able to drill down into individual collections of Books, Authors, Genres and BookInstances, and check out individual documents.

+
+ +

Resumo

+ +

In this article, we've learned a bit about databases and ORMs on Node/Express, and a lot about how Mongoose schema and models are defined. We then used this information to design and implement Book, BookInstance, Author and Genre models for the LocalLibrary website.

+ +

Last of all we tested our models by creating a number of instances (using a standalone script). In the next article we'll look at creating some pages to display these objects.

+ +

Veja também

+ + + +

{{PreviousMenuNext("Learn/Server-side/Express_Nodejs/skeleton_website", "Learn/Server-side/Express_Nodejs/routes", "Learn/Server-side/Express_Nodejs")}}

+ +

Neste módulo

+ + diff --git a/files/pt-br/learn/server-side/express_nodejs/skeleton_website/index.html b/files/pt-br/learn/server-side/express_nodejs/skeleton_website/index.html new file mode 100644 index 0000000000..c6cc459141 --- /dev/null +++ b/files/pt-br/learn/server-side/express_nodejs/skeleton_website/index.html @@ -0,0 +1,509 @@ +--- +title: 'Express Tutorial Parte 2: Criando a estrutura do website' +slug: Learn/Server-side/Express_Nodejs/skeleton_website +translation_of: Learn/Server-side/Express_Nodejs/skeleton_website +--- +
{{LearnSidebar}}
+ +

{{PreviousMenuNext("Learn/Server-side/Express_Nodejs/Tutorial_local_library_website", "Learn/Server-side/Express_Nodejs/mongoose", "Learn/Server-side/Express_Nodejs")}}

+ +

Neste  segundo Express Tutorial , mostrará como criar a estrutura do website que depois você poderá colocar templates, chamadas de banco de dados ou rotas específicas.

+ + + + + + + + + + + + +
Pré-requisitos:Preparar o ambiente de desenvolvimento do Node . Revise o Tutorial Express.
Objetivo:Iniciar nosso website usando o "Express Application Generator".
+ +

Visão Geral

+ +

Nesse artigo mostraremos como criar a estrutura do website usando a ferramenta "Express Application Generator ". Neste caso, usaremos a ferramenta para criar o framework para nosso website "LocalLibrary" , tpara o qual adicionaremos mais tarde todo o outro código necessário para o site. O processo é extremamente simples, com apenas a requisição de invocar o "Generator" na linha de comando com um novo nome de projeto, e, se quiser, especificar o template do site e o gerador de CSS. 

+ +

As seguintes sessões mostrará como chamar o "Application Generator", e prover uma pequena explicação sobre as diferentes opções de CSS. Também aprenderemos como a estrutura do site é definida. No final, será mostrado como podemos rodar o site para ver se funciona.

+ +
+

Nota: O "Express Application Generator"  não é o único gerador para as aplicações do Express, e o projeto gerado não é a única maneira viável de estruturar seus arquivos e diretórios.  O site gerado, entretanto, tem um estrutura modular que é fácil de extender e ser entendida. Para aprender melhor sobre a aplicação do  "minimal Express", veja Exemplo"Hello world" .

+
+ +

Usando o "Application Generator"

+ +

Você já deve ter instalado o gerador como requisito.Como um lembrete rápido, você instala a ferramenta de gerador em todo o site usando o Gerenciador de pacotes NPM, como mostrado:

+ +
npm install express-generator -g
+ +

O gerador tem algumas opções que podem ser visualizadas usando o comando --help (or -h):

+ +
> express --help
+
+    Usage: express [options] [dir]
+
+
+  Options:
+
+        --version        output the version number
+    -e, --ejs            add ejs engine support
+        --pug            add pug engine support
+        --hbs            add handlebars engine support
+    -H, --hogan          add hogan.js engine support
+    -v, --view <engine>  add view <engine> support (dust|ejs|hbs|hjs|jade|pug|twig|vash) (defaults to jade)
+        --no-view        use static html instead of view engine
+    -c, --css <engine>   add stylesheet <engine> support (less|stylus|compass|sass) (defaults to plain css)
+        --git            add .gitignore
+    -f, --force          force on non-empty directory
+    -h, --help           output usage information
+
+ +

Você pode simplesmente especificar express para criar um projeto dentro do diretório atual usando Jade view e CSS simples (se você especificar um nome de diretório, o projeto será criado em uma subpasta com esse nome).

+ +
express
+ +

Também pode ser escolhido um "view" (template) usando--view e/ou um gerador de CSS usando --css.

+ +
+

Nota:  As outras opções para escolher os mecanismos de modelo (e.g. --hogan, --ejs, --hbs etc.) são preteridas. Use --view (ou -v)!

+
+ +

Qual engine de "view" devo usar?

+ +

The Express Application Generator allows you to configure a number of popular view/templating engines, including EJS, Hbs, Pug (Jade), Twig, and Vash, although it chooses Jade by default if you don't specify a view option. Express itself can also support a large number of other templating languages out of the box.

+ +
+

Note: If you want to use a template engine that isn't supported by the generator then see Using template engines with Express (Express docs) and the documentation for your target view engine.

+
+ +

Generally speaking, you should select a templating engine that delivers all the functionality you need and allows you to be productive sooner — or in other words, in the same way that you choose any other component! Some of the things to consider when comparing template engines:

+ + + +
+

Tip: There are many resources on the Internet to help you compare the different options!

+
+ +

For this project, we'll use the Pug templating engine (this is the recently-renamed Jade engine), as this is one of the most popular Express/JavaScript templating languages and is supported out of the box by the generator.

+ +

What CSS stylesheet engine should I use?

+ +

The Express Application Generator allows you to create a project that is configured to use the most common CSS stylesheet engines: LESS, SASS, Compass, Stylus.

+ +
+

Note: CSS has some limitations that make certain tasks difficult. CSS stylesheet engines allow you to use more powerful syntax for defining your CSS and then compile the definition into plain-old CSS for browsers to use.

+
+ +

As with templating engines, you should use the stylesheet engine that will allow your team to be most productive. For this project, we'll use the ordinary CSS (the default) as our CSS requirements are not sufficiently complicated to justify using anything else.

+ +

What database should I use?

+ +

The generated code doesn't use/include any databases. Express apps can use any database mechanism supported by Node (Express itself doesn't define any specific additional behavior/requirements for database management).

+ +

We'll discuss how to integrate with a database in a later article.

+ +

Creating the project

+ +

For the sample Local Library app we're going to build, we'll create a project named express-locallibrary-tutorial using the Pug template library and no CSS stylesheet engine.

+ +

First, navigate to where you want to create the project and then run the Express Application Generator in the command prompt as shown:

+ +
express express-locallibrary-tutorial --view=pug
+
+ +

The generator will create (and list) the project's files.

+ +
   create : express-locallibrary-tutorial\
+   create : express-locallibrary-tutorial\public\
+   create : express-locallibrary-tutorial\public\javascripts\
+   create : express-locallibrary-tutorial\public\images\
+   create : express-locallibrary-tutorial\public\stylesheets\
+   create : express-locallibrary-tutorial\public\stylesheets\style.css
+   create : express-locallibrary-tutorial\routes\
+   create : express-locallibrary-tutorial\routes\index.js
+   create : express-locallibrary-tutorial\routes\users.js
+   create : express-locallibrary-tutorial\views\
+   create : express-locallibrary-tutorial\views\error.pug
+   create : express-locallibrary-tutorial\views\index.pug
+   create : express-locallibrary-tutorial\views\layout.pug
+   create : express-locallibrary-tutorial\app.js
+   create : express-locallibrary-tutorial\package.json
+   create : express-locallibrary-tutorial\bin\
+   create : express-locallibrary-tutorial\bin\www
+
+   change directory:
+     > cd express-locallibrary-tutorial
+
+   install dependencies:
+     > npm install
+
+   run the app:
+     > SET DEBUG=express-locallibrary-tutorial:* & npm start
+ +

At the end of the output, the generator provides instructions on how you install the dependencies (as listed in the package.json file) and then how to run the application (the instructions above are for Windows; on Linux/macOS they will be slightly different).

+ +
+

Note: When using Windows, the && and & assumes you are using the Command Prompt. If you are using the new default PowerShell terminal do not concatenate the commands with && and &. Instead set the DEBUG environment variable with $ENV:DEBUG = "express-locallibrary-tutorial:*";. The npm start can be followed by the npm start. 

+
+ +

Running the skeleton website

+ +

At this point, we have a complete skeleton project. The website doesn't actually do very much yet, but it's worth running it to show how it works.

+ +
    +
  1. First, install the dependencies (the install command will fetch all the dependency packages listed in the project's package.json file). + +
    cd express-locallibrary-tutorial
    +npm install
    +
  2. +
  3. Then run the application. +
      +
    • On Windows, use this command: +
      SET DEBUG=express-locallibrary-tutorial:* & npm start
      +
    • +
    • On macOS or Linux, use this command: +
      DEBUG=express-locallibrary-tutorial:* npm start
      +
      +
    • +
    +
  4. +
  5. Then load http://localhost:3000/ in your browser to access the app.
  6. +
+ +

You should see a browser page that looks like this:

+ +

Browser for default Express app generator website

+ +

You have a working Express application, serving itself to localhost:3000.

+ +
+

Note: You could also start the app just using the npm start command. Specifying the DEBUG variable as shown enables console logging/debugging. For example, when you visit the above page you'll see debug output like this:

+ +
>SET DEBUG=express-locallibrary-tutorial:* & npm start
+
+> express-locallibrary-tutorial@0.0.0 start D:\github\mdn\test\exprgen\express-locallibrary-tutorial
+> node ./bin/www
+
+  express-locallibrary-tutorial:server Listening on port 3000 +0ms
+GET / 304 490.296 ms - -
+GET /stylesheets/style.css 200 4.886 ms - 111
+
+
+ +

Enable server restart on file changes

+ +

Any changes you make to your Express website are currently not visible until you restart the server. It quickly becomes very irritating to have to stop and restart your server every time you make a change, so it is worth taking the time to automate restarting the server when needed.

+ +

One of the easiest such tools for this purpose is nodemon. This is usually installed globally (as it is a "tool"), but here we'll install and use it locally as a developer dependency, so that any developers working with the project get it automatically when they install the application. Use the following command in the root directory for the skeleton project:

+ +
npm install --save-dev nodemon
+ +

If you still choose to install nodemon globally to your machine, and not only to your project's package.json file:

+ +
npm install -g nodemon
+ +

If you open your project's package.json file you'll now see a new section with this dependency:

+ +
 "devDependencies": {
+    "nodemon": "^1.18.10"
+}
+
+ +

Because the tool isn't installed globally we can't launch it from the command line (unless we add it to the path) but we can call it from an NPM script because NPM knows all about the installed packages. Find the the scripts section of your package.json. Initially, it will contain one line, which begins with "start". Update it by putting a comma at the end of that line, and adding the "devstart" line seen below:

+ +
  "scripts": {
+    "start": "node ./bin/www",
+    "devstart": "nodemon ./bin/www"
+  },
+
+ +

We can now start the server in almost exactly the same way as previously, but with the devstart command specified:

+ + + +
+

Note: Now if you edit any file in the project the server will restart (or you can restart it by typing rs on the command prompt at any time). You will still need to reload the browser to refresh the page.

+ +

We now have to call "npm run <scriptname>" rather than just npm start, because "start" is actually an NPM command that is mapped to the named script. We could have replaced the command in the start script but we only want to use nodemon during development, so it makes sense to create a new script command.

+
+ +

The generated project

+ +

Let's now take a look at the project we just created.

+ +

Directory structure

+ +

The generated project, now that you have installed dependencies, has the following file structure (files are the items not prefixed with "/"). The package.json file defines the application dependencies and other information. It also defines a startup script that will call the application entry point, the JavaScript file /bin/www. This sets up some of the application error handling and then loads app.js to do the rest of the work. The app routes are stored in separate modules under the routes/ directory. The templates are stored under the /views directory.

+ +
/express-locallibrary-tutorial
+    app.js
+    /bin
+        www
+    package.json
+    package-lock.json
+    /node_modules
+        [about 6700 subdirectories and files]
+    /public
+        /images
+        /javascripts
+        /stylesheets
+            style.css
+    /routes
+        index.jsusers.js
+    /views
+        error.pug
+        index.puglayout.pug
+
+
+ +

The following sections describe the files in a little more detail.

+ +

package.json

+ +

The package.json file defines the application dependencies and other information:

+ +
{
+  "name": "express-locallibrary-tutorial",
+  "version": "0.0.0",
+  "private": true,
+  "scripts": {
+    "start": "node ./bin/www",
+    "devstart": "nodemon ./bin/www"
+  },
+  "dependencies": {
+    "cookie-parser": "~1.4.3",
+    "debug": "~2.6.9",
+    "express": "~4.16.0",
+    "http-errors": "~1.6.2",
+    "morgan": "~1.9.0",
+    "pug": "2.0.0-beta11"
+  },
+  "devDependencies": {
+    "nodemon": "^1.18.10"
+  }
+}
+
+ +

The dependencies include the express package and the package for our selected view engine (pug). In addition, we have the following packages that are useful in many web applications:

+ + + +

The scripts section defines a "start" script, which is what we are invoking when we call npm start to start the server. From the script definition, you can see that this actually starts the JavaScript file ./bin/www with node. It also defines a "devstart" script, which we invoke when calling npm run devstart instead. This starts the same ./bin/www file, but with nodemon rather than node.

+ +
  "scripts": {
+    "start": "node ./bin/www",
+    "devstart": "nodemon ./bin/www"
+  },
+
+ +

www file

+ +

The file /bin/www is the application entry point! The very first thing this does is require() the "real" application entry point (app.js, in the project root) that sets up and returns the express() application object.

+ +
#!/usr/bin/env node
+
+/**
+ * Module dependencies.
+ */
+
+var app = require('../app');
+
+ +
+

Note: require() is a global node function that is used to import modules into the current file. Here we specify app.js module using a relative path and omitting the optional (.js) file extension.

+
+ +

The remainder of the code in this file sets up a node HTTP server with app set to a specific port (defined in an environment variable or 3000 if the variable isn't defined), and starts listening and reporting server errors and connections. For now you don't really need to know anything else about the code (everything in this file is "boilerplate"), but feel free to review it if you're interested.

+ +

app.js

+ +

This file creates an express application object (named app, by convention), sets up the application with various settings and middleware, and then exports the app from the module. The code below shows just the parts of the file that create and export the app object:

+ +
var express = require('express');
+var app = express();
+...
+module.exports = app;
+
+ +

Back in the www entry point file above, it is this module.exports object that is supplied to the caller when this file is imported.

+ +

Let's work through the app.js file in detail. First, we import some useful node libraries into the file using require(), including http-errors, expressmorgan and cookie-parser that we previously downloaded for our application using NPM; and path, which is a core Node library for parsing file and directory paths.

+ +
var createError = require('http-errors');
+var express = require('express');
+var path = require('path');
+var cookieParser = require('cookie-parser');
+var logger = require('morgan');
+
+ +

Then we require() modules from our routes directory. These modules/files contain code for handling particular sets of related "routes" (URL paths). When we extend the skeleton application, for example to list all books in the library, we will add a new file for dealing with book-related routes.

+ +
var indexRouter = require('./routes/index');
+var usersRouter = require('./routes/users');
+
+ +
+

Note: At this point, we have just imported the module; we haven't actually used its routes yet (this happens just a little bit further down the file).

+
+ +

Next, we create the app object using our imported express module, and then use it to set up the view (template) engine. There are two parts to setting up the engine. First, we set the 'views' value to specify the folder where the templates will be stored (in this case the subfolder /views). Then we set the 'view engine' value to specify the template library (in this case "pug").

+ +
var app = express();
+
+// view engine setup
+app.set('views', path.join(__dirname, 'views'));
+app.set('view engine', 'pug');
+
+ +

The next set of functions call app.use() to add the middleware libraries into the request handling chain. In addition to the 3rd party libraries we imported previously, we use the express.static middleware to get Express to serve all the static files in the /public directory in the project root.

+ +
app.use(logger('dev'));
+app.use(express.json());
+app.use(express.urlencoded({ extended: false }));
+app.use(cookieParser());
+app.use(express.static(path.join(__dirname, 'public')));
+
+ +

Now that all the other middleware is set up, we add our (previously imported) route-handling code to the request handling chain. The imported code will define particular routes for the different parts of the site:

+ +
app.use('/', indexRouter);
+app.use('/users', usersRouter);
+
+ +
+

Note: The paths specified above ('/' and '/users') are treated as a prefix to routes defined in the imported files. So for example, if the imported users module defines a route for /profile, you would access that route at /users/profile. We'll talk more about routes in a later article.

+
+ +

The last middleware in the file adds handler methods for errors and HTTP 404 responses.

+ +
// catch 404 and forward to error handler
+app.use(function(req, res, next) {
+  next(createError(404));
+});
+
+// error handler
+app.use(function(err, req, res, next) {
+  // set locals, only providing error in development
+  res.locals.message = err.message;
+  res.locals.error = req.app.get('env') === 'development' ? err : {};
+
+  // render the error page
+  res.status(err.status || 500);
+  res.render('error');
+});
+
+ +

The Express application object (app) is now fully configured. The last step is to add it to the module exports (this is what allows it to be imported by /bin/www).

+ +
module.exports = app;
+ +

Routes

+ +

The route file /routes/users.js is shown below (route files share a similar structure, so we don't need to also show index.js). First, it loads the express module and uses it to get an express.Router object. Then it specifies a route on that object and lastly exports the router from the module (this is what allows the file to be imported into app.js).

+ +
var express = require('express');
+var router = express.Router();
+
+/* GET users listing. */
+router.get('/', function(req, res, next) {
+  res.send('respond with a resource');
+});
+
+module.exports = router;
+
+ +

The route defines a callback that will be invoked whenever an HTTP GET request with the correct pattern is detected. The matching pattern is the route specified when the module is imported ('/users') plus whatever is defined in this file ('/'). In other words, this route will be used when an URL of /users/ is received.

+ +
+

Tip: Try this out by running the server with node and visiting the URL in your browser: http://localhost:3000/users/. You should see a message: 'respond with a resource'.

+
+ +

One thing of interest above is that the callback function has the third argument 'next', and is hence a middleware function rather than a simple route callback. While the code doesn't currently use the next argument, it may be useful in the future if you want to add multiple route handlers to the '/' route path.

+ +

Views (templates)

+ +

The views (templates) are stored in the /views directory (as specified in app.js) and are given the file extension .pug. The method Response.render() is used to render a specified template along with the values of named variables passed in an object, and then send the result as a response. In the code below from /routes/index.js you can see how that route renders a response using the template "index" passing the template variable "title".

+ +
/* GET home page. */
+router.get('/', function(req, res, next) {
+  res.render('index', { title: 'Express' });
+});
+
+ +

The corresponding template for the above route is given below (index.pug). We'll talk more about the syntax later. All you need to know for now is that the title variable (with value 'Express') is inserted where specified in the template.

+ +
extends layout
+
+block content
+  h1= title
+  p Welcome to #{title}
+
+ +

Challenge yourself

+ +

Create a new route in /routes/users.js that will display the text "You're so cool" at URL /users/cool/. Test it by running the server and visiting http://localhost:3000/users/cool/ in your browser

+ + + +

Summary

+ +

You have now created a skeleton website project for the Local Library and verified that it runs using node. Most importantly, you also understand how the project is structured, so you have a good idea where we need to make changes to add routes and views for our local library.

+ +

Next, we'll start modifying the skeleton so that it works as a library website.

+ +

See also

+ + + +

{{PreviousMenuNext("Learn/Server-side/Express_Nodejs/Tutorial_local_library_website", "Learn/Server-side/Express_Nodejs/mongoose", "Learn/Server-side/Express_Nodejs")}}

+ +

In this module

+ + diff --git a/files/pt-br/learn/server-side/express_nodejs/tutorial_local_library_website/index.html b/files/pt-br/learn/server-side/express_nodejs/tutorial_local_library_website/index.html new file mode 100644 index 0000000000..718e207e86 --- /dev/null +++ b/files/pt-br/learn/server-side/express_nodejs/tutorial_local_library_website/index.html @@ -0,0 +1,93 @@ +--- +title: 'Express: Tutorial para criar o site de uma Biblioteca Local' +slug: Learn/Server-side/Express_Nodejs/Tutorial_local_library_website +tags: + - Express + - Iniciante + - Introdução + - Node + - desenvolvimento-web + - nodejs + - server-side +translation_of: Learn/Server-side/Express_Nodejs/Tutorial_local_library_website +--- +
{{LearnSidebar}}
+ +
{{PreviousMenuNext("Learn/Server-side/Express_Nodejs/development_environment", "Learn/Server-side/Express_Nodejs/skeleton_website", "Learn/Server-side/Express_Nodejs")}}
+ +

Este artigo tem como objetivo explicar o que você vai aprender ao longo dos próximo tutoriais e dar uma visão geral do projeto que vamos desenvolver: um site de "local library" (Biblioteca Local, em tradução livre).

+ + + + + + + + + + + + +
Pré-requisitos:Leia a Indrodução ao Express. Para os próximos artigos, você também precisa ler Conhecendo Node como ambiente de desenvolvimento
Objetivos:Apresentar a aplicação que será desenvolvida ao longo deste tutorial e permitir aos leitores entender quais tópicos serão abordados.
+ +

Visão Geral

+ +

Bem-vindo ao tutorial MDN "Express: Tutorial para criar o site de uma Biblioteca Local", no qual vamos desenvolver um website para gerenciar o catálogo de uma biblioteca. 

+ +

Neste passo a passo você vai: 

+ + + +

Alguns dos itens acima você já conhecebe bem, outros você sabe apenas um pouco. Não se preocupe. Ao final do tutorial, você saberá o sucifiente para desenvolver, por conta própria, um simples app Express.

+ +

O site da Biblioteca Local

+ +

LocalLibrary ou Biblioteca Local é o nome do website que vamos criar durante os tutoriais. O objetivo do site é prover um catálogo para uma pequena biblioteca, onde usuários podem pesquisar livros disponíveis e gerenciar suas contas. 

+ +

Esse exemplo foi escolhido cuidadosamente. Isso porque para construir a "biblioteca" vamos utilizar recursos básicos e fundamentais do Express, além de funcionalidades e conceitos que você poderá aplicar em qualquer outro website:

+ + + +

Apesar de ser um exemplo bem extenso, nossa Biblioteca Local apresentará o mínimo de informações para ajudar você a entender e se desenvolver melhor no uso do Express. A aplicação terá informações sobre livros, cópias de livros, autores e outras informações-chave. Nós não vamos, no entanto, armazenar informações sobre outros itens que a biblioteca pode emprestar e nem vamos oferecer a infraestrutura necessária para suportar os serviços de uma biblioteca grande (de verdade).

+ +

Estou perdido, onde encontro o código-fonte?

+ +

Com o avanço nos tutoriais, forneceremos trechos de códigos para você copiar e colar. Você também receberá trechos apenas com códigos iniciais para completá-los e aprimorá-los por conta própria.

+ +

Dica: Em vez de simplesmente copiar e colar todos os códigos, a sugestão é digitá-los. Isso ajuda você a se familiarizar com a sintaxe, melhorando o nível de aprendizado.

+ +

Se ficar perdido no meio do caminho, fique calmo. Você pode acessar o código inteiro pelo Github.

+ +
+

Nota:  As versões específicas do Node, Express e outros módulos que adotados no tutorial estão listados no arquivo package.json.

+
+ +

Sumário

+ +

Agora que você entedeu o que é o site "Biblioteca Local " e o que vamos aprender ao longo do projeto, é hora de criar nossa estrutura de pastas e arquivos.

+ +

{{PreviousMenuNext("Learn/Server-side/Express_Nodejs/development_environment", "Learn/Server-side/Express_Nodejs/skeleton_website", "Learn/Server-side/Express_Nodejs")}}

+ +

Neste módulo

+ + -- cgit v1.2.3-54-g00ecf