express: 5. archivos estáticos

Cómo enviar archivos estáticos mediante el middleware __static

Georgia O'Keeffe

archivado en: JavaScript / 23 Octubre, 2015 / taller:

En la entrada anterior de esta serie dedicada a express expliqué que existe un middleware -esto es, una o más funciones que se intercalan entre la petición (request) y la respuesta(response)- relacionado con los archivos estáticos, cuya gestión vamos a ver en esta entrada. Pero antes vamos a aprender a montar un proyecto express en menos de dos minutos ^^.

Si algo caracteriza el mundo node es la sencillez y rapidez con que se pueden hacer las cosas y buen ejemplo de eso es el generador de proyectos express que podemos usar por consola. Por pasos:

1. Instalamos el generador de forma global:

$ npm install express-generator -g

2. Creamos y nos movemos a un directorio:

$ mkdir miDirectorio

$ cd miDirectorio

3. Creamos el proyecto:

express miservidor

4. Nos movemos al proyecto e instalamos las dependencias:

cd miproyecto

npm install

Y ¡ale op! con este par de sentencias tenemos todo el tinglado montado en un periquete. Algo así:

miservidor/

bin

node_modules

public/

images

javascripts

stylesheets

style.css

routes/

index.js

users.js

views/

error.jade

index.jade

layout.jade

package.json

Enviar archivos estáticos

El código de cada uno de los archivos que vienen en el generador no nos interesa ahora, ya volveremos más adelante sobre esos patrones de diseño. Lo que sí es importante es que nos fijemos en ese directorio public, que podemos llamar de cualquier manera, en el que vamos a guardar nuestros recursos estáticos, es decir, todo aquello que no es una plantilla (de jade, handelbars o lo que sea) ni un servicio ni forma parte del core del servidor. Para entendernos: las páginas html, el javaScript, las imágenes, las hojas de estilo, etcétera.

Para que se entienda mejor lo que sigue antes vamos a crear una página html que tenga cosas enlazadas (imágenes, archivos js y estilos). La podemos llamar index.html y la guardamos en la raíz de public.

miservidor/public/index.html

<!doctype html>

<html lang="es">

<head>

<meta charset="utf-8">

<title>demo Express: recursos estáticos</title>

<link rel="stylesheet" href="stylesheets/normalize.css">

<link rel="stylesheet" href="stylesheets//main.css">

<script src="javascripts/vendor/modernizr-2.8.3.min.js"></script>

</head>

<body>

<h1>Haga Basin!</h1>

<img src="images/mi-imagen.jpg">

</body>

</html>

Para enviar archivos estáticos se utiliza el método sendFile() del objeto response, el cual admite tres parámetros: la ruta absoluta del recurso que queremos mandar y, opcionales, un objeto en el que se definen distintas configuraciones y una función callback para gestionar los errores.

La ruta absoluta la podemos saber con el objeto global de node __dirname, por lo que solo necesitaríamos definir algo así en app.js para que se enviara nuestro index.html:

 app.js

var express = require("express");

var app = express();

app.get('/', function (req, res) {

res.sendFile(__dirname +'/public/index.html');

});

app.use(function(req, res) {

res.status(404).send('404: ahí no hay ná de ná', 404);

});

app.use(function(err, req, res, next) {

res.status(500).send('500: Sa roto!');

});

var server = app.listen(3000, function () {

console.log('Servidor levantado en el puerto 3000');

});

Nos estamos aproximando a la solución, sin embargo, este método tiene un problema y es que solo devuelve los recursos que se indican específicamente y no encuentra todo el resto de cosas que se solicitan a partir de la carga de la página, tal y como podemos apreciar desde la consola del chrome si nos vamos a la pestaña network.

Una solución sería definir tantos sendFiles() como recursos esperamos que nos soliciten...

app.get('/images/mi-imagen.jpg', function (req, res) {

res.sendFile(__dirname +'/public/images/mi-imagen.jpg');

});

pero si tuviéramos que hacer algo así para cada página html, cada imagen, cada audiovisual, cada script y cada hoja de estilo de una web nos podríamos volver tarumbas. Dont Panic! que tenemos a nuestra disposición __static : ).

El middleware __static

Este middleware se basa en las rutas en cascada que vimos en entradas anteriores: express va mirando por orden cada una de las rutas definidas hasta que encuentra la que se le está solicitando. Por lo tanto, podemos hacer algo así:

1. Si la ruta es foo, usa foo

2. Si la ruta es bar, usa bar

3. Y si lo que nos están pidiendo no es ni foo ni bar, por ejemplo, todas las imágenes o las hojas de estilo o el js, entonces usa este directorio que te digo ahora mediante __static.

En código expressiano:

app.get('/foo', function (req, res) {

res.send("Enviando foo");

});

app.get('/bar', function (req, res) {

res.send("Enviando bar");

});

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

app.use(function(req, res) {

res.status(404).send('404: ahí no hay ná de ná', 404);

});

app.use(function(err, req, res, next) {

res.status(500).send('500: Sa roto!');

});

 

De esa manera, si algo no está en las rutas indicadas, express mirará en public, o donde queramos poner los archivos, y si ya ni siquiera lo encuentra ahí mandará un error 404. Chulo, ¿no? Pues no se vayan todavía, que aún hay más que diría Supe Ratón.

Opciones

Podemos configurar algunas opciones de static en un jasonako que se pasa como segundo parámetro, opcional, a la función.

var opcionesStatic = {

//

}

app.use(express.static('public', opcionesStatic));

Las opciones principales que podemos definir son:

a) index

Por defecto es index.html e indica qué pagina debe usarse como index, es decir, cuál debe utilizarse cuando se solicita el directorio raíz (/). Por ejemplo, así indicaríamos que debe enviarse foo.html.

app.use(express.static('public', {index: "foo.html"}));

b) dotfiles

En general, se precede con un punto el nombre de los archivos o directorios que deben ser ignorados, tanto en las peticiones a un servidor como en escenarios de otra naturaleza como los repos git, donde toda la configuración de este controlador de versiones se incluye en el directorio .git. En un servidor apache, por poner otro ejemplo, es normal definir algunas opciones que nunca deben llegar al cliente en el archivo .haccess. Bueno, pues con este parámetro indicamos cómo deben tratarse las peticiones a los archivos precedidos por un punto. Las opciones son:

  • "ignore": ignorar (no enviar, es la opción por defecto).
  • "deny": denegar (no enviar).
  • "allow": enviar.

c) etags

Mediante un valor booleano (true o false) definimos si el servidor utilizará o no ETags, del inglés entity tag, para el cacheo de archivos. El valor por defecto es true.

d) lastModified

Al igual que sucede con etags, este parámetro está relacionado con las cabeceras (headers), un tema relacionado con el protocolo http que veremos con más detalle en la próxima entrada. Sirve para indicar si queremos (true) o no (false) enviar este dato en el header, el cual indica cuándo se modificó por última vez un archivo.

e) maxAge

Es otro parámetro relacionado con la caché, un tema sobre el que volveré más adelante, que sirve para definir en milisegundos su tiempo de vida máximo.

Bueno, me dejo algunas cosas en el tintero, pero más o menos con lo expuesto ya podemos empezar a enviar archivos estáticos sin problemas. Por hoy lo dejo aquí.

|| Tags: , , ,

valoración de los lectores sobre express: 5. archivos estáticos

  • estrellica valoración positiva
  • estrellica valoración positiva
  • estrellica valoración positiva
  • estrellica valoración positiva
  • estrellica valoración positiva
  • 5 sobre 5 (1 votos)

¿Te ha parecido útil o interesante esta entrada?
dormido, valoración 1 nadapensativo, valoración 2 un poco sonrisa, valoración 3 a medias guiño, valoración 4 bastante aplauso, valoración 5 mucho

Tú opinión es muy importante, gracias por compartirla!

Aportar un comentario

*