Entrega archivos estáticos

A menudo las aplicaciones necesitan entregar archivos estáticos, como JavaScript, imágenes y CSS, además de controlar solicitudes dinámicas. Las apps en el entorno flexible pueden entregar archivos estáticos desde una opción de Google Cloud, como Cloud Storage, entregarlos directamente o usar una red de distribución de contenidos (CDN) de terceros.

Entrega archivos desde Cloud Storage

Cloud Storage puede alojar elementos estáticos para aplicaciones web dinámicas. Estos son algunos de los beneficios de entregarlos desde Cloud Storage en lugar de hacerlo desde tu aplicación:

  • Cloud Storage funciona básicamente como una red de distribución de contenidos. No requiere configuraciones especiales gracias a que, según la configuración predeterminada, cualquier objeto público de lectura se almacena en caché en la red global de Cloud Storage.
  • La carga de tu aplicación se aligerará porque Cloud Storage se encargará de la entrega de elementos estáticos. Según la cantidad de elementos estáticos que tengas y la frecuencia de acceso, esto puede reducir en gran medida el costo por ejecutar tu app.
  • Los cargos de ancho de banda por acceder a contenido a menudo pueden ser menores con Cloud Storage.

Puedes subir tus elementos a Cloud Storage mediante la herramienta de línea de comandos de gsutil o la API de Cloud Storage.

La biblioteca cliente de Google Cloud proporciona un cliente idiomático a Cloud Storage para almacenar y recuperar datos con Cloud Storage en una app de App Engine.

Ejemplo de entrega desde un bucket de Cloud Storage

En este ejemplo simple se muestra cómo crear un bucket de Cloud Storage y subir elementos estáticos mediante Google Cloud CLI:

  1. Crea un bucket. Es común, pero no obligatorio, nombrar al bucket según el ID del proyecto. Debe tener un nombre único a nivel global.

    gsutil mb gs://<your-bucket-name>
    
  2. Configura la LCA para otorgar acceso de lectura a los elementos del bucket.

    gsutil defacl set public-read gs://<your-bucket-name>
    
  3. Sube elementos al bucket. El comando rsync suele ser la forma más rápida y fácil de subir y actualizar elementos. También puedes usar cp.

    gsutil -m rsync -r ./static gs://<your-bucket-name>/static
    

Ahora puedes acceder a los elementos estáticos a través de https://storage.googleapis.com/<your-bucket-name>/static/....

Para obtener más detalles sobre cómo entregar elementos estáticos, incluso cómo entregarlos desde un nombre de dominio personalizado con Cloud Storage, consulta Cómo alojar un sitio web estático.

Entrega archivos desde otros servicios de Google Cloud

También tienes la opción de usar Cloud CDN o algún otro servicio de almacenamiento de Google Cloud.

Entrega archivos directamente desde la app

Generalmente, la entrega de archivos desde tu aplicación resulta simple. Sin embargo, existen algunas desventajas, por lo que debes tener en cuenta lo siguiente:

  • Para las solicitudes de archivos estáticos, se usan recursos que deberían usarse con solicitudes dinámicas.
  • En función de tu configuración, puede que la entrega de archivos desde tu aplicación ocasione una latencia de respuesta y genere problemas cuando se creen instancias nuevas de control de cargas.

Ejemplo de entrega de archivos estáticos con la app

Comienza a usarlo

En el siguiente ejemplo, se muestra cómo entregar archivos estáticos con la app para la versión 1.15 y anteriores del entorno de ejecución de Go, y la versión 1.18 y posteriores. Ten en cuenta que debes actualizar tu app.yaml para usar la versión nueva. Consulta el entorno de ejecución de Python para obtener más información sobre el uso de los nuevos entornos de ejecución.

Puedes usar los archivos estándar http.FileServer o http.ServeFile para entregar archivos directamente desde tu app.

v1.18 y posteriores


// Package static demonstrates a static file handler for App Engine flexible environment.
package main

import (
	"fmt"
	"net/http"

	"google.golang.org/appengine"
)

func main() {
	// Serve static files from "static" directory.
	http.Handle("/static/", http.FileServer(http.Dir(".")))

	http.HandleFunc("/", homepageHandler)
	appengine.Main()
}

const homepage = `<!doctype html>
<html>
<head>
  <title>Static Files</title>
  <link rel="stylesheet" type="text/css" href="/static/main.css">
</head>
<body>
  <p>This is a static file serving example.</p>
</body>
</html>`

func homepageHandler(w http.ResponseWriter, r *http.Request) {
	fmt.Fprint(w, homepage)
}

v1.15 y anteriores


// Package static demonstrates a static file handler for App Engine flexible environment.
package main

import (
	"fmt"
	"net/http"

	"google.golang.org/appengine"
)

func main() {
	// Serve static files from "static" directory.
	http.Handle("/static/", http.FileServer(http.Dir(".")))

	http.HandleFunc("/", homepageHandler)
	appengine.Main()
}

const homepage = `<!doctype html>
<html>
<head>
  <title>Static Files</title>
  <link rel="stylesheet" type="text/css" href="/static/main.css">
</head>
<body>
  <p>This is a static file serving example.</p>
</body>
</html>`

func homepageHandler(w http.ResponseWriter, r *http.Request) {
	fmt.Fprint(w, homepage)
}

Java

En el siguiente ejemplo, se muestra cómo entregar archivos estáticos con tu app para el entorno de ejecución de Java 8 y la versión 11/17. Ten en cuenta que debes actualizar tu app.yaml para usar la versión nueva. Consulta el entorno de ejecución de Java para obtener más información sobre el uso de los nuevos entornos de ejecución.

El contenedor de servlet del entorno de ejecución de Java usará el descriptor de implementación, el archivo web.xml, para mapear las URLs a los servlets, incluidos los elementos estáticos. Si no especificas un archivo web.xml, se usa uno predeterminado que mapea todo al servlet predeterminado.

En este ejemplo, ./src/main/webapp/index.html hace referencia a una hoja de estilo entregada desde /stylesheets/styles.css.

version 11/17

<!doctype html>
<html>
<head>
<title>Static Files</title>
<link rel="stylesheet" type="text/css" href="/stylesheets/styles.css">
</head>
<body>
  <p>This is a static file serving example.</p>
</body>
</html>

versión 8

<!doctype html>
<html>
<head>
<title>Static Files</title>
<link rel="stylesheet" type="text/css" href="/stylesheets/styles.css">
</head>
<body>
  <p>This is a static file serving example.</p>
</body>
</html>

El archivo styles.css se encuentra en ./src/main/webapp/stylesheets/styles.css.

body {
  font-family: Verdana, Helvetica, sans-serif;
  background-color: #CCCCFF;
}

Puedes configurar de manera explícita cómo se controlan los archivos estáticos en el archivo web.xml. Por ejemplo, si deseas mapear solicitudes a todos los archivos que tengan la extensión .jpg, haz lo siguiente:

<servlet-mapping>
    <servlet-name>default</servlet-name>
    <url-pattern>*.jpg</url-pattern>
</servlet-mapping>

Si usas un framework web como Play, deberás consultar la documentación del framework sobre los elementos estáticos.

Node.js

En el siguiente ejemplo, se muestra cómo entregar archivos estáticos con tu app para la versión 16 y anteriores del entorno de ejecución de Node.js y la versión 18 y posteriores. Ten en cuenta que debes actualizar tu app.yaml para usar la versión nueva. Consulta el entorno de ejecución de Node.js para obtener más información sobre el uso de los nuevos entornos de ejecución.

La mayoría de los frameworks web incluyen asistencia para entregar archivos estáticos. En este ejemplo, la aplicación usa el middleware express.static para entregar archivos del directorio ./public a la URL /static.

'use strict';

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

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

// Use the built-in express middleware for serving static files from './public'
app.use('/static', express.static('public'));

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

// Start the server
const PORT = parseInt(process.env.PORT) || 8080;
app.listen(PORT, () => {
  console.log(`App listening on port ${PORT}`);
  console.log('Press Ctrl+C to quit.');
});

La vista se refiere a /static/main.css.

doctype html
html(lang="en")
  head
    title Static Files
    meta(charset='utf-8')
    link(rel="stylesheet", href="/static/main.css")
  body
    p This is a static file serving example.

La hoja de estilo se encuentra en ./public/css, que se entrega desde /static/main.css.

body {
  font-family: Verdana, Helvetica, sans-serif;
  background-color: #CCCCFF;
}

Por lo general, otros marcos de trabajo de Node.js, como Hapi, Koa y Sails, admiten la entrega de archivos estáticos directamente desde la aplicación. Consulta su documentación para obtener detalles sobre cómo configurar y usar contenido estático.

PHP

El entorno de ejecución de PHP activa nginx para entregar tu app, que está configurada con el fin de entregar archivos estáticos en el directorio del proyecto. Para declarar la raíz del documento, especifica document_root en el archivo app.yaml:

runtime: php
env: flex

runtime_config:
  document_root: web

Python

En el siguiente ejemplo, se muestra cómo entregar archivos estáticos con la app para la versión 3.7 y anteriores del entorno de ejecución de Python. Para la versión 3.8 y posteriores de Python, consulta Entorno de ejecución de Python a fin de obtener más información sobre el uso de versiones más recientes.

La mayoría de los frameworks web incluyen asistencia para entregar archivos estáticos. En este ejemplo, la app usa la función incorporada de Flask para entregar archivos en el directorio ./static desde la URL /static.

La aplicación incluye una vista que procesa la plantilla. De forma automática, Flask entrega todo en el directorio ./static sin configuración adicional.

import logging

from flask import Flask, render_template

app = Flask(__name__)

@app.route("/")
def hello():
    """Renders and serves a static HTML template page.

    Returns:
        A string containing the rendered HTML page.
    """
    return render_template("index.html")

@app.errorhandler(500)
def server_error(e):
    """Serves a formatted message on-error.

    Returns:
        The error message and a code 500 status.
    """
    logging.exception("An error occurred during a request.")
    return (
        f"An internal error occurred: <pre>{e}</pre><br>See logs for full stacktrace.",
        500,
    )

if __name__ == "__main__":
    # This is used when running locally. Gunicorn is used to run the
    # application on Google App Engine. See entrypoint in app.yaml.
    app.run(host="127.0.0.1", port=8080, debug=True)

La plantilla que la vista procesa incluye una hoja de estilo ubicada en /static/main.css.

<!doctype html>
<html>
<head>
  <title>Static Files</title>
  <!--
  Flask automatically makes files in the 'static' directory available via
  '/static'.
  -->
  <link rel="stylesheet" type="text/css" href="/static/main.css">
</head>
<body>
  <p>This is a static file serving example.</p>
</body>
</html>

La hoja de estilo se encuentra en ./static/main.css.

body {
  font-family: Verdana, Helvetica, sans-serif;
  background-color: #CCCCFF;
}

Otros frameworks de Python, como Django, Pyramid y Bottle, suelen admitir la entrega de archivos estáticos directamente desde la app. Consulta su documentación para obtener detalles sobre cómo configurar y usar el contenido estático.

Ruby

La mayoría de los frameworks web incluyen asistencia para entregar archivos estáticos. El siguiente ejemplo demuestra cómo entregar archivos estáticos con tu aplicación para el entorno de ejecución de Ruby para la versión 3.1 y anteriores, y la versión 3.2. Ten en cuenta que debes actualizar tu archivo app.yaml para usar la versión nueva. Consulta el entorno de ejecución de Ruby para obtener más información sobre el uso de los nuevos entornos de ejecución.

Sinatra

El framework web de Sinatra entrega archivos del directorio ./public de forma predeterminada. Esta app incluye una vista que hace referencia a /application.css.

body {
  font-family: Verdana, Helvetica, sans-serif;
  background-color: #CCCCFF;
}

La hoja de estilo se encuentra en ./public/application.css, que se entrega desde /application.css.

Ruby en Rails

El framework web de Ruby on Rails entrega archivos del directorio ./public de forma predeterminada. Los archivos estáticos de JavaScript y CSS también se pueden generar mediante la canalización de elementos de Rails.

Estas aplicaciones de ejemplo contienen una vista de diseño que incluye todas las hojas de estilo de la aplicación:

versión 3.2

doctype html
html
  head
    title Serving Static Files
    link rel="stylesheet" href="/application.css"
    script src="/application.js"
  body
    p This is a static file serving example.

versión 3.1 y anteriores:

doctype html
html
  head
    title Serving Static Files
    = stylesheet_link_tag "application", media: "all"
    = javascript_include_tag "application"
    = csrf_meta_tags
  body
    = yield

versión 3.2

La hoja de estilo es un archivo .css que se encuentra en ./public/application.css.

body {
  font-family: Verdana, Helvetica, sans-serif;
  background-color: #CCCCFF;
}

versión 3.1 y anteriores:

La hoja de estilo es un archivo Sass que se encuentra en ./app/assets/stylesheets/main.css.sass.

body
  font-family: Verdana, Helvetica, sans-serif
  background-color: #CCCCFF

De forma predeterminada, las apps de Rails no generan ni entregan elementos estáticos cuando se ejecutan en producción.

El entorno de ejecución de Ruby ejecuta rake assets:precompile durante la implementación a fin de generar recursos estáticos y establece la variable de entorno RAILS_SERVE_STATIC_FILES para habilitar la entrega de archivos estáticos en producción.

.NET

En el siguiente ejemplo, se muestra cómo entregar archivos estáticos con tu app para la versión 3.1 y anteriores del entorno de ejecución de .NET y la versión 6 y posteriores. Ten en cuenta que debes actualizar tu archivo app.yaml para usar la versión nueva. Consulta el entorno de ejecución de .NET para obtener más información sobre el uso de los nuevos entornos de ejecución.

versión 6 y posteriores

<html>
<head>
    <meta charset="utf-8" />
    <title>Hello Static World</title>
</head>
<body>
    <p>This is a static html document.</p>
    <p><img src="trees.jpg" /></p>
</body>
</html>

Para habilitar la entrega de archivos estáticos, agrega lo siguiente:

app.UseDefaultFiles();
app.UseStaticFiles();

versión 3.1 y anteriores:

<html>
<head>
    <meta charset="utf-8" />
    <title>Hello Static World</title>
</head>
<body>
    <p>This is a static html document.</p>
    <p><img src="trees.jpg" /></p>
</body>
</html>

Para habilitar la entrega de archivos estáticos, agrega lo siguiente:

app.UseDefaultFiles();
app.UseStaticFiles();

Entrega archivos desde una red de distribución de contenidos de terceros

Puedes utilizar cualquier CDN externa de terceros para entregar tus archivos estáticos y almacenar las solicitudes dinámicas en caché, aunque tu app podría experimentar un aumento de latencia y costo.

Para un mejor rendimiento, usa una CDN de terceros compatible con CDN Interconnect.