1. Code
  2. JavaScript
  3. Node

Construir Aplicaciones Web Usando Node.js

Aparte de construcción API, Node.js es ideal para crear aplicaciones web estándar. Tiene potentes herramientas para satisfacer el gusto de los desarrolladores web. En este tutorial, construir una aplicación web que puede servir como una biblioteca.
Scroll to top

Spanish (Español) translation by James (you can also view the original English article)

Introducción

Aparte de construcción API, Node.js es ideal para crear aplicaciones web estándar. Tiene potentes herramientas para satisfacer el gusto de los desarrolladores web. En este tutorial, construir una aplicación web que puede servir como una biblioteca.

Edificio para conocer algunos tipos de middleware, verá cómo gestionar el envío del formulario en Node.js, y usted también podrá hacer referencia a dos modelos.

Vamos a empezar.

Para Empezar

Empiece instalando el generador expreso en su máquina.

1
npm install express-generator -g

Ejecute el comando expreso generador para generar la aplicación.

1
express tutsplus-library --view=pug
1
   create : tutsplus-library
2
   create : tutsplus-library/package.json
3
   create : tutsplus-library/app.js
4
   create : tutsplus-library/public
5
   create : tutsplus-library/routes
6
   create : tutsplus-library/routes/index.js
7
   create : tutsplus-library/routes/users.js
8
   create : tutsplus-library/views
9
   create : tutsplus-library/views/index.pug
10
   create : tutsplus-library/views/layout.pug
11
   create : tutsplus-library/views/error.pug
12
   create : tutsplus-library/bin
13
   create : tutsplus-library/bin/www
14
   create : tutsplus-library/public/javascripts
15
   create : tutsplus-library/public/images
16
   create : tutsplus-library/public/stylesheets
17
   create : tutsplus-library/public/stylesheets/style.css
18
19
   install dependencies:
20
     $ cd tutsplus-library && npm install

21


22
   run the app:
23
     $ DEBUG=tutsplus-library:* npm start

Ahora emigran a su trabajo, abra package.json y las dependencias similares a lo que tengo debajo.

1
#package.json
2
3
{
4
  "name": "tutsplus-library",
5
  "version": "0.0.0",
6
  "private": true,
7
  "scripts": {
8
    "start": "node ./bin/www"
9
  },
10
  "dependencies": {
11
    "body-parser": "~1.17.1",
12
    "connect-flash": "^0.1.1",
13
    "cookie-parser": "~1.4.3",
14
    "debug": "~2.6.3",
15
    "express": "~4.15.2",
16
    "express-messages": "^1.0.1",
17
    "express-session": "^1.15.5",
18
    "express-validator": "^4.2.1",
19
    "mongoose": "^4.11.12",
20
    "morgan": "~1.8.1",
21
    "pug": "~2.0.0-beta11",
22
    "serve-favicon": "~2.4.2"
23
  }
24
}

Ejecute el comando para instalar los paquetes.

1
npm install

Configurar el Archivo de Entrada

app.js se creó cuando ejecutó el comando generador; sin embargo, usted necesita configurar configuración extra. Edite el archivo para ver como lo que tengo debajo.

1
#app.js
2
3
var express = require('express');
4
var path = require('path');
5
var favicon = require('serve-favicon');
6
var logger = require('morgan');
7
var cookieParser = require('cookie-parser');
8
var bodyParser = require('body-parser');
9
const session = require('express-session')
10
const expressValidator = require('express-validator')
11
const flash = require('connect-flash')
12
const mongoose = require('mongoose')
13
14
// 1

15
const genres = require('./routes/genres');
16
const books = require('./routes/books');
17
18
var app = express();
19
20
// 2

21
mongoose.Promise = global.Promise
22
const mongoDB = process.env.MONGODB_URI || 'mongodb://127.0.0.1/tutsplus-library'
23
mongoose.connect(mongoDB)
24
25
// view engine setup

26
app.set('views', path.join(__dirname, 'views'));
27
app.set('view engine', 'pug');
28
29
// uncomment after placing your favicon in /public

30
//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));

31
app.use(logger('dev'));
32
app.use(bodyParser.json());
33
app.use(bodyParser.urlencoded({ extended: false }));
34
app.use(cookieParser());
35
app.use(express.static(path.join(__dirname, 'public')));
36
37
// 3

38
app.use(session({
39
  secret: 'secret',
40
  saveUninitialized: true,
41
  resave: true
42
}))
43
44
// 4

45
app.use(expressValidator({
46
  errorFormatter: function(param, msg, value) {
47
    var namespace = param.split('.')
48
    , root = namespace.shift()
49
    , formParam = root
50
51
    while(namespace.length) {
52
      formParam += '[' + namespace.shift() + ']'
53
    }
54
    return {
55
      param : formParam,
56
      msg : msg,
57
      value : value
58
    }
59
  }
60
}))
61
62
// 5

63
app.use(flash())
64
app.use(function (req, res, next) {
65
  res.locals.messages = require('express-messages')
66
  next()
67
})
68
69
// 6

70
app.use('/genres', genres);
71
app.use('/books', books);
72
73
// catch 404 and forward to error handler

74
app.use(function(req, res, next) {
75
  var err = new Error('Not Found');
76
  err.status = 404;
77
  next(err);
78
});
79
80
// error handler

81
app.use(function(err, req, res, next) {
82
  // set locals, only providing error in development

83
  res.locals.message = err.message;
84
  res.locals.error = req.app.get('env') === 'development' ? err : {};
85
86
  // render the error page

87
  res.status(err.status || 500);
88
  res.render('error');
89
});
90
91
module.exports = app;
  1. Se requiere las dos rutas que va a hacer usan de en la construcción de esta aplicación. Se creará el archivo de rutas poco. Las rutas necesarias son asignadas como valores a dos variables diferentes que se utilizan al configurar el software intermedio para las rutas.
  2. Establece Mangosta para uso global.Promise.  La variable MongoDB se asigna la MONGODB_URI de su entorno o la ruta de acceso al servidor local de mongo. Esta variable se pasa como un argumento para conectarse al servidor de MongoDB corriente.
  3. Configurar middleware sesión usando express-session.  Este middleware es importante ya que mostrando mensajes flash en algunas partes de su aplicación.
  4. Configurar middleware para la validación. Este middleware se utilizará para validar el formulario de entrada, asegurando que los usuarios de la aplicación no presente una forma vacía. La validación utiliza un paquete instalado, express-validator.
  5. Configurar middleware que será muy útil al mostrar mensajes flash. Este middleware hace uso de connect-flash.
  6. Se establecen las rutas de la aplicación hasta hacer uso del archivo de rutas que usted requirió. Pide apuntando a /genres y /books hará uso de los géneros y los libros rutas de archivos respectivamente. En este momento no ha creado los archivos de rutas, pero haremos pronto.

Libro y Modelo de Género

El modelo de libro hará uso de mangosta esquema para definir cómo se estructurarán los libros. Crear un directorio llamado models y un nuevo archivo llamado Book.js. Aquí es lo que parece.

1
#models/Book.js
2
3
const mongoose = require('mongoose')
4
mongoose.Promise = global.Promise
5
const Schema = mongoose.Schema
6
7
const bookSchema = Schema({
8
  name: {
9
    type: String,
10
    trim: true,
11
    required: 'Please enter a book name'
12
  },
13
  description: {
14
    type: String,
15
    trim: true
16
  },
17
  author: {
18
    type: String,
19
    trim: true,
20
  },
21
  genre: [{
22
    type: Schema.Types.ObjectId,
23
    ref: 'Genre'
24
  }]
25
})
26
27
module.exports = mongoose.model('Book', bookSchema)

Aquí tienes cuatro campos. El último campo se utiliza para almacenar cada libro pertenece al género. Aquí el campo de género hace referencia al modelo de género, que se creará a continuación. Por eso el tipo se establece en Schema.Types.ObjectId, que es donde se guardarán los ID de cada género se hace referencia. Ref especifica el modelo se está haciendo referencia a. Tenga en cuenta que este género está guardado como una matriz, lo que significa que un libro puede tener más de un género.

Vamos a seguir adelante a crear el modelo de Género.

1
#models/genre.js
2
3
const mongoose = require('mongoose')
4
mongoose.Promise = global.Promise
5
const Schema = mongoose.Schema
6
7
const genreSchema = Schema({
8
  name: {
9
    type: String,
10
    trim: true,
11
    required: 'Please enter a Genre name'
12
  }
13
})
14
15
module.exports = mongoose.model('Genre', genreSchema)

Para su género, necesita un campo: name.

Género Indice de Ruta y Visión

Para este tutorial, usted hará uso de dos rutas de senderos para su género: un camino para añadir nuevos géneros y otro que recoge los géneros tienes. Crear un archivo en su directorio de rutas llamado genres.js.

Empezar por exigir a todos los módulos que va a hacer uso.

1
#routes/genres.js
2
3
var express = require('express');
4
var router = express.Router();
5
const mongoose = require('mongoose')
6
const Genre = require('../models/Genre')

A continuación, caer en la ruta que controla el archivo de índice para sus géneros.

1
router.get('/', (req, res, next) => {
2
  const genres = Genre.find({}).exec()
3
    .then((genres) => {
4
      res.render('genres', { genres: genres })
5
  }, (err) => {
6
    throw err
7
  })
8
});

Esta ruta se llama siempre que las solicitudes se realizan a /genres. Aquí se llama al método find en el modelo de género para obtener todos los géneros que se han creado. Estos géneros se procesan luego en un template llamado genres. Vamos a seguir adelante y crear que, pero en primer lugar, actualizar tu layout.pug a este aspecto:

1
#views/layout.pug
2
3
doctype html
4
html
5
  head
6
    title= title
7
    link(rel='stylesheet', href='/stylesheets/style.css')
8
    link(rel='stylesheet', href='https://bootswatch.com/paper/bootstrap.css')
9
    script(src='https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js')
10
    script(src='https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js')
11
  body
12
    .container-fluid
13
      block header
14
        nav.navbar.navbar-inverse
15
          .container-fluid
16
            .navbar-header
17
              button.navbar-toggle.collapsed(type='button', data-toggle='collapse', data-target='#bs-example-navbar-collapse-2')
18
                span.sr-only Toggle navigation
19
                span.icon-bar
20
                span.icon-bar
21
                span.icon-bar
22
              a.navbar-brand(href='#') Local Library
23
            #bs-example-navbar-collapse-2.collapse.navbar-collapse
24
              ul.nav.navbar-nav.navbar-right
25
                li
26
                  a(href='/books') View Books
27
                li
28
                  a(href='/books/add') Add New Book
29
                li
30
                  a(href='/genres') View Genres
31
                li
32
                  a(href='/genres/add') Add New Genre
33
        block content

Esto le dará su punto de vista una buena estructura para facilitar la navegación. Ahora cree un archivo de vista llamado genre.pug. En este archivo, será recorrer los géneros creados y salida de cada género en una lista desordenada.

Aquí está cómo debe buscar el archivo.

1
#views/genres.pug
2
3
extends layout
4
5
block content
6
  h1 Genre
7
  ul.well.well-lg
8
    each genre, i in genres
9
      li.well.well-sm
10
        p #{genre.name}

Añadir Vistas y Nuevas Rutas de Género

Volver a su routes/genres.js para agregar las rutas que se encargará de la creación de nuevos géneros.

1
#routes/genres.js
2
3
// 1

4
router.get('/add', (req, res, next) => {
5
  res.render('addGenre')
6
})
7
8
// 2

9
router.post('/add', (req, res, next) => {
10
  req.checkBody('name', 'Name is required').notEmpty()
11
12
  const errors = req.validationErrors()
13
14
  if (errors) {
15
    console.log(errors)
16
    res.render('addgenres', { genre, errors })
17
  }
18
19
  const genre = (new Genre(req.body)).save()
20
    .then((data) => {
21
      res.redirect('/genres')
22
    })
23
    .catch((errors) => {
24
      console.log('oops...')
25
      console.log(errors)
26
    })
27
})
28
29
// 3

30
module.exports = router;
  1. El trabajo de este router es simplemente Mostrar la página para agregar nuevas rutas. Este router se llama siempre que las solicitudes se hacen a /genres/add camino.
  2. Este router encarga de la presentación del formulario. Cuando se envía el formulario, verifique que un nombre es introducido por el usuario. Si no se ha introducido ningún nombre, la página es nuevamente procesada. Si los controles son buenos ir, se guarda el género y el usuario es redirigido a la página de /genres.
  3. El módulo se exporta como un router.

Ahora puede seguir adelante y crear la página para agregar un nuevo género.

1
#views/addGenre.pug
2
3
extends layout
4
5
block content
6
  .row
7
    .col-md-12
8
      h1 Add Book
9
      form(method="POST", action="/genres/add")
10
        .form-group
11
          label.col-lg-2.control.label Name
12
          .col-lg-10
13
            input.form-control(type="text", name='name')
14
        .form-group
15
          .col-lg-10.col-lg-offset-2
16
            input.button.btn.btn-primary(type='submit', value='Submit')
17
      
18
      if errors
19
        ul
20
          for error in errors
21
            li!= error.msg

Libros de Rutas y Vistas

Crear un nuevo archivo de ruta para los libros y asígnele el nombre books.js. Como lo hizo antes con el género, empezar por la que requieren los módulos necesarios.

1
#routes/books.js
2
3
var express = require('express');
4
var router = express.Router();
5
const mongoose = require('mongoose')
6
const Book = require('../models/Book')
7
const Genre = require('../models/Genre')

A continuación, configurar el router para la visualización de todos los libros guardados en la biblioteca. Tratar de por su propia cuenta de la manera como se estableció del género; Usted puede comprobar siempre hacia atrás para hacer las correcciones.

Supongo que conoces – aquí es cómo debe buscar.

1
router.get('/', (req, res, next) => {
2
  const books = Book.find({}).exec().then((books) => {
3
    res.render('books', { books: books })
4
  }, (err) => {
5
    throw err
6
  })
7
});

Cuando se llama a este router, se hace una solicitud para encontrar todos los libros guardados en la base de datos. Si todo va bien, los libros se muestran en la página de /books, otro que se produce un error.

Es necesario crear un nuevo archivo para la visualización de todos los libros, y aquí está cómo debe buscar.

1
#views/books.pug
2
3
extends layout
4
5
block content
6
  h1 Books
7
  ul.well.well-lg
8
    each book, i in books
9
      li.well.well-sm
10
        a(href=`/books/show/${book.id}`) #{book.name}
11
        p= book.description

Simplemente recorrer los libros devueltos y salida el nombre y descripción de cada libro con una lista desordenada. El nombre de los puntos de libro a la página individual del libro.

Añadir Vistas y Nuevas Rutas de Libro

El siguiente router que configurar encargará de la adición de nuevos libros. Aquí se utilizarán dos routers: uno simplemente hará que la página, y otro encargará de la presentación del formulario.

Este es el aspecto de los routers.

1
router.get('/add', (req, res, next) => {
2
  const genres = Genre.find({}).exec()
3
    .then((genres) => {
4
      res.render('addBooks', { genres })
5
    })
6
    .catch((err) => {
7
      throw err
8
    })
9
})
10
11
router.post('/add', (req, res, next) => {
12
  req.checkBody('name', 'Name is required').notEmpty()
13
  req.checkBody('description', 'Description is required').notEmpty()
14
  req.checkBody('genre', 'Genre is required').notEmpty
15
16
  const errors = req.validationErrors()
17
18
  if (errors) {
19
    console.log(errors)
20
    res.render('addBooks', { book, errors })
21
  }
22
23
  const book = (new Book(req.body)).save()
24
    .then((data) => {
25
      res.redirect('/books')
26
    })
27
    .catch((errors) => {
28
      console.log('oops...')
29
    })
30
})

En el primer router, se muestra la página de /addBooks. Este router se llama cuando se hace una petición a /add ruta de acceso. Desde libros añadidos se suponen que tienen los géneros, que desea mostrar los géneros que se han salvado a la base de datos.

1
  const genres = Genre.find({}).exec()
2
      .then((genres) => {

El código anterior todos los géneros encuentra en la base de datos y devuelve en los variable géneros. Con esto, usted será capaz de recorrer los géneros y mostrarlos como casillas de verificación.

El segundo router encarga de la presentación del formulario. En primer lugar, se compruebe el cuerpo de la solicitud para asegurarse de que algunos campos no están vacíos. Aquí es donde el middleware express-validator que establece en app.js práctico. Si hay errores, la página es nuevamente procesada. Si no hay ninguno, la nueva instancia de libro se guarda y se redirige al usuario a la página de /books.

Vamos a ir adelante y crear los puntos de vista para esto.

Crear un nuevo archivo de vista llamado addBooks.pug. Tenga en cuenta que el nombre de la vista coincida con el primer parámetro dado a res.render. Esto es porque están haciendo una plantilla. Durante la redirección, simplemente pase la ruta de acceso que desea redirigir, como lo hizo con res.redirect('/books').

Habiendo establecido, aquí es lo que deberían ser los puntos de vista.

1
#views/addBooks.pug
2
3
extends layout
4
5
block content
6
  .row
7
    .col-md-12
8
      h1 Add Book
9
      form(method="POST", action="/books/add")
10
        .form-group
11
          label.col-lg-2.control-label Name
12
          .col-lg-10
13
            input.form-control(type="text", name='name')
14
        .form-group
15
          label.col-lg-2.control-label Author
16
          .col-lg-10
17
            input.form-control(type="text", name='author')
18
        .form-group
19
          label.col-lg-2.control-label Book Description
20
          .col-lg-10
21
            textarea#textArea.form-control(rows='3', name='description')
22
        .form-group
23
          label.col-lg-2.control-label Genre
24
          .col-lg-10
25
            for genre in genres
26
              .checkbox
27
                input.checkbox(type='checkbox', name='genre', id=genre._id, value=genre._id, checked=genre.checked)
28
                label(for=genre._id) #{genre.name}
29
        .form-group
30
          .col-lg-10.col-lg-offset-2
31
            input.button.btn.btn-primary(type='submit', value='Submit')
32
      
33
      if errors
34
        ul
35
          for error in errors
36
            li!= error.msg

Lo importante a notar aquí es la acción de la forma y el método. Cuando se hace clic en el botón Enviar, usted está haciendo una solicitud POST a /books/add. Otra cosa, una vez más se recorrer la colección de géneros volvió y cada uno de ellos.

Libro Ver Ruta y Visión

Nos dejó caer en la ruta para gestionar las peticiones realizadas a cada página de libros. Mientras estás allí, es importante el módulo de exportación también.

1
#routes/books.js
2
3
router.get('/show/:id', (req, res, next) => {
4
  const book = Book.findById({ _id: req.params.id })
5
  .populate({
6
    path: 'genre',
7
    model: 'Genre',
8
    populate: {
9
      path: 'genre',
10
      model: 'Book'
11
    }
12
  })
13
  .exec()
14
    .then((book) => {
15
      res.render('book', { book })
16
    })
17
    .catch((err) => {
18
      throw err
19
    })
20
})
21
22
module.exports = router;

Ninguna magia sucede aquí.

En primer lugar, las solicitudes para este router deben tener un id: el id del libro. Este identificador se obtiene de los parámetros de la petición mediante req.params.id. Esto se utiliza para identificar el libro específico que debe obtenerse de la base de datos, como los identificadores son únicos. Cuando el libro se encuentra, el valor de género del libro se rellena con todos los géneros que se han salvado a esta instancia de libro. Si todo va bien, se representa la vista de libro, que se produce un error.

Vamos a crear la vista para un libro. Aquí está cómo debe buscar.

1
block content
2
  .well.well-lg
3
    h1 #[strong Name:] #{book.name}
4
    ul
5
      li #[strong Description:] #{book.description}
6
      li #[strong Author]: #{book.author}
7
      li #[strong Genre:]
8
        each genre in book.genre
9
          #{genre.name}
10
          |,

Usted puede iniciar su servidor nodo ejecutando:

1
DEBUG=tutsplus-library:* npm start

Conclusión

Ya sabes cómo crear una aplicación web estándar en Node.js, no sólo una aplicación de tareas simples. Fuiste capaz de manejar el envío del formulario, dos modelos de referencia y establecer algunos middleware.

Puede ir más lejos mediante la extensión de la aplicación, trate de añadir la capacidad de eliminar un libro. Primero agregar un botón a la página del show, ir a los archivos de rutas y añadir un router para esto. Tenga en cuenta que esto va a ser una solicitud POST.

También se puede pensar más características para agregar a la aplicación. Espero que lo disfruté.