Skip to content

Latest commit

 

History

History
768 lines (594 loc) · 16.6 KB

File metadata and controls

768 lines (594 loc) · 16.6 KB

shieldsIO shieldsIO shieldsIO

WideImg

Máster en Programación FullStack con JavaScript y Node.js

JS, Node.js, Frontend, Backend, Firebase, Express, Patrones, HTML5_APIs, Asincronía, Websockets, Testing

Clase 68

Server Render Clásico

Esquema

Claves

  • La lógica de negocio esta en el Backend
  • El backend realiza todas las consultas y obtiene toda la información
  • De forma dinámica el Backend genera una respuesta con un contenido HTML válido
  • El javascript del front se limita a la interacción con el usuario pero no gestiona data como en arquitecturas SPA (Single Page Application)

Express: ¿Cómo debo estructurar mi aplicación de Express?

CURL

Esquema

CURL

curl -I 127.0.0.1:3000 # Solo cabeceras
curl -o fichero https://fictizia.com/ # Guardar salida en un fichero
curl -O https://domain.com/file.zip # Guardar un fichero
curl -o fichero.zip https://domain.com/file.zip # Guardar un fichero con otro nombre

Otras Herramientas

Express: Template engines

Esquema

Las claves

  • Debemos guardar las plantillas en la carpeta views
  • Todas las plantillas tienen ficheros con su extensión especifica
  • Es necesario definir el view engine que se utilizará
  • Una vez establecida la propiedad view engine, no tiene que especificar el motor ni cargar el módulo de motor de plantilla en la aplicación
  • Utilizaremos res.render() para renderizar una plantilla.
  • Los motores de plantillas sorportados en express deben seguir Consolidate.js

Motores soportados

Ejemplo rápido con PUG

// npm install express pug

const express = require('express'),
    app = express();

//Middelware
app.set('view engine', 'pug');

//Rutas
app.get('/', (req, res) => {
  res.render('index.pug')
});

// Puerto
app.listen(8080, () => {
  console.log('localhost:8080 up & running!');
});

Jade

Jade_logo

Recursos

PUG (antes Jade)

Shame meme gif

Jade no existe más...

PUG

Pug_logo

Migración

Implementaciones en otros lenguajes

Herramientas

Recursos

PUG: Sintaxis

Pug_logo

Lo básico

//- http://naltatis.github.io/jade-syntax-docs/#basics
doctype html
html
  head
    title my jade template
  body
    h1 Hello #{name}
{"name": "Bob"}
<!DOCTYPE html>
<!DOCTYPE html>
<html>
  <head>
    <title>my jade template</title>
  </head>
  <body>
    <h1>Hello Bob</h1>
  </body>
</html>

Comentarios

//- http://naltatis.github.io/jade-syntax-docs/#comments
// single line comment
//- invisible single line comment


// block comment
  h1 hello world
//- invisible block comment
  h2 how are you?


<!--[if IE 8]>
script(src='/ie.js')
<![endif]-->
<!-- single line comment-->


<!-- block commenth1 hello world
-->


<!--[if IE 8]>
<script src="/ie.js"></script><![endif]-->

Id y Class

//- http://naltatis.github.io/jade-syntax-docs/#basics
#content
  .block
    input#bar.foo1.foo2
<div id="content">
  <div class="block">
    <input id="bar" class="foo1 foo2"/>
  </div>
</div>

Anidación

//- http://naltatis.github.io/jade-syntax-docs/#nesting
//- OPCION 1
ul#books
  li
    a(href="#book-a") Book A
  li
    a(href="#book-b") Book B

//- OPCION 2
ul#books
  li: a(href="#book-a") Book A
  li: a(href="#book-b") Book B
<ul id="books">
  <li><a href="#book-a">Book A</a></li>
  <li><a href="#book-b">Book B</a></li>
</ul>

Textos

//- http://naltatis.github.io/jade-syntax-docs/#text
//- OPCIÓN 1
p
  | foo bar
  | hello world
  
//- OPCIÓN 2
p.
  foo bar
  hello world
<p>
  foo bar
  hello world
</p>

Texto con variables

//- http://naltatis.github.io/jade-syntax-docs/#text
h1 foo
h2= book.name
h3 "#{book.name}" for #{book.price}
{"book": {"name": "Hello", "price": 12.99}}
<h1>foo</h1>
<h2>Hello</h2>
<h3>"Hello" for 12.99 €</h3>

Variables (desde la plantilla)

//- http://naltatis.github.io/jade-syntax-docs/#variables
//- OPCIÓN 1
- var foo = "hello world"
h1= foo

//- OPCIÓN 2
- var foo = book.name + " world"
h1= foo
{"book": {"name": "hello"}}
<h1>hello world</h1>

Escapado

//- http://naltatis.github.io/jade-syntax-docs/#escaping
li Hello <em>World</em>

li= name
li!= name

li Say #{name}
li Say !{name}
{"name": "Hello <em>World</em>"}
<li>Hello <em>World</em></li>

<li>Hello &lt;em&gt;World&lt;/em&gt;</li>
<li>Hello <em>World</em></li>

<li>Say Hello &lt;em&gt;World&lt;/em&gt;</li>
<li>Say Hello <em>World</em></li>

Atributos

//- http://naltatis.github.io/jade-syntax-docs/#attributes
input(type="text", placeholder="your name")

input(type=type, value='Hello #{name}')

input(checked=true, disabled=false)
{"type": "text", "name": "Bob"}
<input type="text" placeholder="your name"/>

<input type="text" value="Hello Bob"/>

<input checked="checked"/>

Condicionales: if, else, else if y unless

//- http://naltatis.github.io/jade-syntax-docs/#if

if name == "Bob"
  h1 Hello Bob
else if name == "Peter"
  h1 Hello Peter
else
  h1 My name is #{name}


unless errors
  p no errors
{"name": "Bob", "errors": false}
<h1>Hello Bob</h1>

<p>no errors</p>

Case

//- http://naltatis.github.io/jade-syntax-docs/#case
case name
  when "Bob"
    p Hi Bob!
  when "Alice"
    p Howdy Alice!
  default
    p Hello #{name}!
{"name": "Bob"}
<p>Hi Bob!</p>

for y each

//- http://naltatis.github.io/jade-syntax-docs/#for
select
  each book, i in books
    option(value=i) Book #{book}


ul
  for book in special_books
    li= special_book
  else
    li sorry, no books!
{"books": ["A", "B", "C"], "special_books": []}
<select>
  <option value="0">Book A</option>
  <option value="1">Book B</option>
  <option value="2">Book C</option>
</select>

<ul>
  <li>sorry, no books!</li>
</ul>

Mixin

//- http://naltatis.github.io/jade-syntax-docs/#mixin

mixin book(name, price)
  li #{name} for #{price} €
  
ul#books
  +book("Book A", 12.99)
  +book("Book B", 5.99)
<ul id="books">
  <li>Book A for 12.99 €</li>
  <li>Book B for 5.99 €</li>
</ul>

Código

//- https://pugjs.org/language/code.html

- for (var x = 0; x < 3; x++)
  li item

-
  var list = ["Uno", "Dos", "Tres",
          "Cuatro", "Cinco", "Seis"]
each item in list
  li= item
<li>item</li>
<li>item</li>
<li>item</li>


<li>Uno</li>
<li>Dos</li>
<li>Tres</li>
<li>Cuatro</li>
<li>Cinco</li>
<li>Seis</li>

Filters

//- https://pugjs.org/language/filters.html
//- Filters are rendered at compile time. 
//- $ npm install --save jstransformer-coffee-script jstransformer-markdown-it

:markdown-it(linkify langPrefix='highlight-')
  # Markdown

  Markdown document with http://links.com and

 `var codeBlocks;`

script
  :coffee-script
    console.log 'This is coffee script'
<h1>Markdown</h1>
<p>Markdown document with <a href="http://links.com">http://links.com</a> and</p>
<pre><code class="highlight-js">var codeBlocks;
</code></pre>
<script>
  (function() {
    console.log('This is coffee script');

  }).call(this);
</script>

Includes

//- https://pugjs.org/language/includes.html

//- index.pug
doctype html
html
  include includes/head.pug
  body
    h1 My Site
    p Welcome to my super lame site.
    include includes/foot.pug

//- includes/head.pug
head
  title My Site
  script(src='/javascripts/jquery.js')
  script(src='/javascripts/app.js')

//- includes/foot.pug
footer#footer
  p Copyright (c) foobar
<!DOCTYPE html>
<html>

<head>
  <title>My Site</title>
  <script src="/javascripts/jquery.js"></script>
  <script src="/javascripts/app.js"></script>
</head>

<body>
  <h1>My Site</h1>
  <p>Welcome to my super lame site.</p>
  <footer id="footer">
    <p>Copyright (c) foobar</p>
  </footer>
</body>

</html>

PUG: Migración a Pug 2 (desde Jade o Pug 1.x)

Pug_logo

Legacy Mixin Call

//- old

a(href='#{link}')

a(href='before#{link}after')
//- new

a(href=link)

//- (on Node.js/io.js ≥ 1.0.0)
a(href=`before${link}after`) 
//- (everywhere)
a(href='before' + link + 'after')

Prefixed each Syntax

//- old

- each a in b
  = a

- for a in b
  = a
//- new

each a in b
  = a

for a in b
  = a

Más

Pug en la práctica con Express

server.js

// npm install express body-parser pug

const express = require('express'),
    bodyParser = require('body-parser'),
    app = express();

//Middelware
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }))
app.set('view engine', 'pug');

//Rutas
app.get('/', (req, res) => {
  res.render('index.pug')
});

app.post('/', (req, res) => {
  res.json(req.body);
});

app.get('/hola', (req, res) => {
  res.send('hola!');
});

app.get('/hola/:usuario', (req, res) => {
  res.send('Hola ' + req.params.usuario + '. Hemos abierto una nueva ruta personalizada!');
});

app.get('/consulta/:usuario', (req, res) => {
  var datos = {
    marca: "Seat",
    modelo: "Ibiza",
    edad: 20,
    ITVPasada: true,
    seguroPasado: true
  };

  res.render('consulta.pug', {
    usuario: req.params.usuario,
    datos: datos
  });
});

// Puerto
app.listen(8080, () => {
  console.log('localhost:8080 up & running!');
});

views/consulta.pug

.datos
  h3 Datos: 
  p= "El Coche de "+usuario+" es un "+datos.marca+" "+datos.modelo
    
  h3 Detalles técnicos:
  ul
      li= "ITV en regla: " +datos.ITVPasada 
      li= "seguro en regla: " +datos.seguroPasado

views/index.pug

section.container
h1 Manda tu mensaje!

form(method='post', action='/')
  fieldset
    legend Mandame tu mensaje:
    p.contenido
      label Tu mensaje
      input(name='mensaje')
    p.acciones
      input(type='submit', value='Enviar')

Ejercicios

1 - Migra la aplicación de MovieFire para hacer server render con Nodejs y Pug

Claves:

  • Puedes usar librerías como request, pug, morgan, helmet, firebase...
  • ⚠️ reutilizaremos este ejercicio en el futuro con otras bases de datos, asi que intentan aislar y abstraer la conexión a la base de datos ;-)

Plantillas:

  • index.pug para el listado general de películas
  • details.pug para los detalles de una película
  • error.pug para mostrar errores

Rutas:

  • [GET] / Muestra todas las películas
  • [GET] /create/:name Crea una pelicula
  • [GET] /film/:id Muestra los detalles de una película en concreto
  • [POST] /film/:id/delete Borra una película
  • [POST] /film/:id/update Actualiza el nombre de una película

Estructura de datos por película:

{
  "details" : {
    "Actors" : "Ralph Fiennes, Michael Gambon, Alan Rickman, Daniel Radcliffe",
    "Awards" : "Nominated for 3 Oscars. Another 45 wins & 91 nominations.",
    "BoxOffice" : "$381,000,185",
    "Country" : "USA, UK",
    "DVD" : "11 Nov 2011",
    "Director" : "David Yates",
    "Genre" : "Adventure, Drama, Fantasy, Mystery",
    "Language" : "English",
    "Metascore" : "87",
    "Plot" : "Harry, Ron, and Hermione search for Voldemort's remaining Horcruxes in their effort to destroy the Dark Lord as the final battle rages on at Hogwarts.",
    "Poster" : "https://m.media-amazon.com/images/M/MV5BMjIyZGU4YzUtNDkzYi00ZDRhLTljYzctYTMxMDQ4M2E0Y2YxXkEyXkFqcGdeQXVyNTIzOTk5ODM@._V1_SX300.jpg",
    "Production" : "Warner Bros. Pictures",
    "Rated" : "PG-13",
    "Ratings" : [ {
      "Source" : "Internet Movie Database",
      "Value" : "8.1/10"
    }, {
      "Source" : "Rotten Tomatoes",
      "Value" : "96%"
    }, {
      "Source" : "Metacritic",
      "Value" : "87/100"
    } ],
    "Released" : "15 Jul 2011",
    "Response" : "True",
    "Runtime" : "130 min",
    "Title" : "Harry Potter and the Deathly Hallows: Part 2",
    "Type" : "movie",
    "Website" : "http://www.HarryPotter.com/",
    "Writer" : "Steve Kloves (screenplay), J.K. Rowling (novel)",
    "Year" : "2011",
    "imdbID" : "tt1201607",
    "imdbRating" : "8.1",
    "imdbVotes" : "673,121"
  },
  "name" : "harry potter"
}

Solución

2 - Mejora MovieFire Objetivos:

  • Unifica la estructura de datos (quita details) y normaliza las propiedades (sin capitalización)
  • Usa Bootstrap e includes de Pug
  • Manten una buena estructura separando rutas y modelos, puedes usar async/await para simplificar el trabajo

Solución