Saltearse al contenido

@astrojs/ cloudflare

Un adaptador SSR para usar con los objetivos de las funciones de Cloudflare Pages. Escribe tu código en Astro/Javascript y despliegalo en Cloudflare Pages.

Agrega el adaptador de Cloudflare para habilitar el SSR en tu proyecto de Astro con el comando astro add. Esto instalará el adaptador y realizará los cambios necesarios en tu archivo astro.config.mjs en un solo paso.

Ventana de terminal
# Usando NPM
npx astro add cloudflare
# Usando Yarn
yarn astro add cloudflare
# Usando PNPM
pnpm astro add cloudflare

Si prefieres instalar el adaptador manualmente en su lugar, sigue los siguientes dos pasos:

  1. Agrega el adaptador de Cloudflare como una dependencia de tu proyecto utilizando el gestor de paquetes de tu preferencia. Si estás utilizando npm o no estás seguro, ejecuta el siguiente comando en la terminal:
Ventana de terminal
npm install @astrojs/cloudflare
  1. Agrega lo siguiente a tu archivo astro.config.mjs:
astro.config.mjs
import { defineConfig } from 'astro/config';
import cloudflare from '@astrojs/cloudflare';
export default defineConfig({
output: 'server',
adapter: cloudflare(),
});

mode: "advanced" | "directory"

Por defecto "advanced"

Esta opción de configuración define cómo se despliega tu proyecto de Astro en Cloudflare Pages.

  • El modo advanced recoge el archivo _worker.js de la carpeta dist
  • El modo directory recoge los ficheros de la carpeta functions, por defecto sólo se genera un fichero [[path]].js.

Cambiar al modo de directorio te permite añadir manualmente archivos adicionales como plugins de Cloudflare Pages, Cloudflare Pages Middleware o funciones personalizadas utilizando enrutamiento de funciones de Cloudflare Pages.

astro.config.mjs
export default defineConfig({
adapter: cloudflare({ mode: 'directory' }),
});

En el modo directory, el adaptador compilará la parte del lado del cliente de tu aplicación de la misma manera que en el modo advanced de forma predeterminada, pero moverá el script del worker a una carpeta functions en la raíz del proyecto. En este caso, el adaptador solo colocará un archivo [[path]].js en esa carpeta, lo que te permitirá agregar plugins adicionales y middleware de páginas que pueden ser incluidos en el control de versiones.

Para compilar un paquete separado para cada página, establece la opción functionPerRoute en la configuración de tu adaptador de Cloudflare. Esta opción requiere un mantenimiento manual de la carpeta functions. Los archivos emitidos por Astro sobrescribirán los archivos existentes con nombres idénticos en la carpeta functions, por lo que debes elegir nombres de archivo únicos para cada archivo que añadas manualmente. Además, el adaptador nunca vaciará la carpeta functions de archivos obsoletos, por lo que deberás limpiar la carpeta manualmente cuando elimines páginas.

astro.config.mjs
import {defineConfig} from "astro/config";
import cloudflare from '@astrojs/cloudflare';
export default defineConfig({
adapter: cloudflare({
mode: 'directory',
functionPerRoute: true
})
})

Este adaptador no admite el uso de edgeMiddleware.

routes.strategy: "auto" | "include" | "exclude"

por defecto "auto"

Determina como routes.json será generado si no se provee un _routes.json personalizado.

Hay tres opciones disponibles:

  • "auto" (por defecto): Seleccionará automáticamente la estrategia que genere la menor cantidad de entradas. Esto debería ser casi siempre suficiente, así que elige esta opción a menos que tengas una razón específica para no hacerlo.

  • include: Las páginas y endpoints que no sean pre-renderizados se enumeran como entradas include, indicando a Cloudflare que invoque estas rutas como funciones. Las entradas exclude solo se utilizan para resolver conflictos. Por lo general, la mejor estrategia cuando tu sitio web tiene principalmente páginas estáticas y solo algunas páginas o endpoints dinámicos.

    Ejemplo: Para src/pages/index.astro (estático), src/pages/company.astro (estático), src/pages/users/faq.astro (estático) y src/pages/users/[id].astro (SSR) esto producirá el siguiente _routes.json:

    {
    "version": 1,
    "include": [
    "/_image", // Endpoint de imagen de Astro
    "/users/*" // Ruta dinámica
    ],
    "exclude": [
    // Las rutas estáticas que deben estar exentas de la ruta dinámica de comodín anterior
    "/users/faq/",
    "/users/faq/index.html"
    ]
    }

    exclude: Las páginas pre-renderizadas se enumeran como entradas exclude (indicando a Cloudflare que maneje estas rutas como activos estáticos). Por lo general, la mejor estrategia cuando tu sitio web tiene principalmente páginas o endpoints dinámicos y solo algunas páginas estáticas.

    Ejemplo: Para las mismas páginas que en el ejemplo anterior, esto producirá el siguiente _routes.json:

    {
    "version": 1,
    "include": [
    "/*" // Toma todo como función excepto las rutas a continuación
    ],
    "exclude": [
    // Todos los archivos estáticos
    "/",
    "/company/",
    "/index.html",
    "/users/faq/",
    "/favicon.png",
    "/company/index.html",
    "/users/faq/index.html"
    ]
    }

routes.include: string[]

por defecto []

Si quieres usar la generación automática de _routes.json, pero quieres incluir rutas adicionales (por ejemplo, cuando tienes funciones personalizadas en la carpeta functions), puedes usar la opción routes.include para agregar rutas adicionales al array include.

routes.exclude: string[]

por defecto []

Si quieres usar la generación automática de _routes.json, pero quieres excluir rutas adicionales, puedes usar la opción routes.exclude para agregar rutas adicionales al array exclude.

El siguiente ejemplo automáticamente genera _routes.json mientras incluye y excluye rutas adicionales. Ten en cuenta que esto solo es necesario si tienes funciones personalizadas en la carpeta functions que no son manejadas por Astro.

astro.config.mjs
export default defineConfig({
adapter: cloudflare({
mode: 'directory',
routes: {
strategy: 'include',
include: ['/users/*'], // // manejado por una función personalizada: functions/users/[id].js
exclude: ['/users/faq'], // manejado por una página estática: pages/users/faq.astro
},
}),
});

imageService: "passthrough" | "cloudflare"

Determina qué servicio de imágenes es utilizado por el adaptador. El adaptador utilizará el modo passthrough de forma predeterminada cuando se configure un servicio de imágenes incompatible. De lo contrario, utilizará el servicio de imágenes configurado globalmente:

wasmModuleImports: boolean

por defecto: false

Importar o no archivos .wasm directamente como módulos ES usando la sintaxis de importación .wasm?module.

Añade wasmModuleImports: true a astro.config.mjs para habilitar esta funcionalidad tanto en la compilación de Cloudflare como en el servidor de desarrollo de Astro. Lee más sobre el uso de módulos Wasm

astro.config.mjs
import {defineConfig} from "astro/config";
import cloudflare from '@astrojs/cloudflare';
export default defineConfig({
adapter: cloudflare({
wasmModuleImports: true
}),
output: 'server'
})

Consulta el repositorio de Cloudflare para obtener más información sobre el tipo CF_BINDING

runtime: { mode: 'off' } | { mode: 'local'; type: 'pages'; persistTo?: string; bindings?: Record<string, CF_BINDING> } | { mode: 'local'; type: 'workers'; persistTo?: string; };

por defecto: { mode: 'off', persistTo: '' }

Determina si y como el Runtime de Cloudflare es añadido a astro dev. Lee más sobre el tiempo de ejecución de Cloudflare.

La propiedad type define donde tu proyecto de Astro es desplegado:

La propiedad mode define lo que quieres que el tiempo de ejecución soporte en astro dev:

  • off: no tiene acceso al tiempo de ejecución usando astro dev. Alternativamente, puedes usar Vista previa con Wrangler cuando necesites acceso al tiempo de ejecución, para simular el entorno de producción localmente.
  • local: utiliza un tiempo de ejecución local alimentado por miniflare y workerd, que soporta los Bindings de Cloudflare. Solo si quieres usar características no soportadas, como eval, bindings sin soporte local elige Vista previa con Wrangler

En mode: local, tienes acceso a la propiedad persistTo que define donde se guarda el estado de los bindings locales. Esto evita que se generen bindings nuevos cada vez que se reinicia el servidor de desarrollo. Este valor es un directorio relativo a la ruta de ejecución de astro dev. Por defecto se establece en .wrangler/state/v3 para permitir el uso de los comandos de la interfaz de línea de comandos de wrangler (por ejemplo, para las migraciones). Añade esta ruta a tu .gitignore.

El tiempo de ejecución de Cloudflare te proporciona acceso a las variables de entorno y a los bindings de Cloudflare. Puedes encontrar más información en la documentación de Workers y Pages de Cloudflare. Dependiendo de tu tipo de despliegue (pages o workers), necesitas configurar los bindings de forma diferente.

Los bindings actualmente admitidos son:

Las Cloudflare Pages no admiten un archivo de configuración.

Para desplegar tu proyecto de páginas en producción, necesitas configurar los bindings usando el Panel de Control de Cloudflare. Para poder acceder a los bindings localmente, necesitas configurarlos usando la opción runtime del adaptador.

astro.config.mjs
import { defineConfig } from 'astro/config';
import cloudflare from '@astrojs/cloudflare';
export default defineConfig({
output: 'server',
adapter: cloudflare({
runtime: {
mode: 'local',
type: 'pages',
bindings: {
// ejemplo de una variable de binding (variable de entorno)
"URL": {
type: "var",
value: "https://example.com",
},
// ejemplo de un binding KV
"KV": {
type: "kv",
},
// ejemplo de un binding D1
"D1": {
type: "d1",
},
// ejemplo de un binding R2
"R2": {
type: "r2",
},
// ejemplo de un Durable Object binding
"DO": {
type: "durable-object",
className: "DO",
},
},
},
}),
});

Si también necesitas definir secrets además de las variables de entorno, necesitas añadir un archivo .dev.vars a la raíz del proyecto de Astro:

DB_PASSWORD=miContraseña

Si quieres usar wrangler para los comandos de la cli, por ejemplo, las migraciones de D1, también necesitas añadir un wrangler.toml a la raíz del proyecto de Astro con el contenido correcto. Consulta la documentación de Cloudflare para más detalles.

wrangler.toml
name = "ejemplo"
compatibility_date = "2023-06-14"
# ejemplo para el binding D1
[[d1_databases]]
binding = "D1"
database_name = "D1"
database_id = "D1"
preview_database_id = "D1"

Para desplegar tu proyecto de workers en producción, necesitas configurar los bindings usando un archivo de configuración wrangler.toml en la raíz de tu proyecto de Astro. Para poder acceder a los bindings localmente, el adaptador @astrojs/cloudflare también leerá el archivo wrangler.toml.

wrangler.toml
name = "example"
# ejemplo de un Binding de KV
kv_namespaces = [
{ binding = "KV", id = "KV", preview_id = "KV" },
]
# ejemplo de una variable de binding (variables de entorno)
[vars]
URL = "example.com"
# ejemplo de un Binding de D1
[[d1_databases]]
binding = "D1"
database_name = "D1"
database_id = "D1"
preview_database_id = "D1"
# ejemplo de un Binding de R2
[[r2_buckets]]
binding = 'R2'
bucket_name = 'R2'
# ejemplo de un Durable Object Binding
[[durable_objects.bindings]]
name = "DO"
class_name = "DO"

Si también necesitas definir secrets además de las variables de entorno, necesitas añadir un archivo .dev.vars a la raíz del proyecto de Astro:

DB_PASSWORD=myPassword

Puedes acceder al runtime desde los componentes de Astro a través de Astro.locals dentro de cualquier archivo .astro.

src/pages/index.astro
---
const runtime = Astro.locals.runtime;
---
<pre>{JSON.stringify(runtime.env)}</pre>

Puedes acceder al runtime desde los endpoints de la API a través de context.locals:

src/pages/api/someFile.js
export function GET(context) {
const runtime = context.locals.runtime;
return new Response('Algún cuerpo');
}

Si has configurado mode: advanced, puedes escribir el objeto runtime usando AdvancedRuntime:

src/env.d.ts
/// <reference types="astro/client" />
type KVNamespace = import('@cloudflare/workers-types/experimental').KVNamespace;
type ENV = {
SERVER_URL: string;
KV_BINDING: KVNamespace;
};
type Runtime = import('@astrojs/cloudflare').AdvancedRuntime<ENV>;
declare namespace App {
interface Locals extends Runtime {
user: {
name: string;
surname: string;
};
}
}

Si has configurado mode: directory, puedes escribir el objeto runtime usando DirectoryRuntime:

src/env.d.ts
/// <reference types="astro/client" />
type KVNamespace = import('@cloudflare/workers-types/experimental').KVNamespace;
type ENV = {
SERVER_URL: string;
KV_BINDING: KVNamespace;
};
type Runtime = import('@astrojs/cloudflare').DirectoryRuntime<ENV>;
declare namespace App {
interface Locals extends Runtime {
user: {
name: string;
surname: string;
};
}
}

Puedes adjuntar cabeceras personalizadas a tus respuestas añadiendo un archivo _headers en la carpeta public/ de tu proyecto de Astro. Este archivo se copiará al directorio de salida de tu compilación.

Puedes declarar redirecciones personalizadas utilizando Cloudflare Pages. Esto te permite redirigir las peticiones a una URL diferente. Puedes añadir un archivo _redirects en la carpeta public/ de tu proyecto de Astro. Este archivo se copiará en el directorio de salida de tu compilación.

Puedes definir qué rutas invocan funciones y cuáles son assets estáticos, utilizando el enrutamiento de Cloudflare a través de un archivo _routes.json. Este archivo es generado automáticamente por Astro.

Por defecto, @astrojs/cloudflare generará un archivo _routes.json con reglas include y exclude basadas en las rutas dinámicas y estáticas de tu aplicación. Esto permitirá a Cloudflare servir archivos y procesar redirecciones estáticas sin invocar una función. La creación de un _routes.json personalizado anulará esta optimización automática. Consulta la documentación de Cloudflare sobre la creación de un routes.json personalizado para más detalles.

El siguiente es un ejemplo de importación de un módulo Wasm que luego responde a las solicitudes sumando los parámetros numéricos de la solicitud.

pages/add/[a]/[b].js
import mod from '../util/add.wasm?module';
// crea una instancia de antes para compartir el módulo
const addModule: any = new WebAssembly.Instance(mod);
export async function GET(context) {
const a = Number.parseInt(context.params.a);
const b = Number.parseInt(context.params.b);
return new Response(`${addModule.exports.add(a, b)}`);
}

Mientras que este ejemplo es trivial, Wasm puede ser utilizado para acelerar operaciones computacionalmente intensivas que no involucran operaciones I/O significativas, como incrustar una biblioteca de procesamiento de imágenes.

El adaptador de Cloudflare de Astro te permite utilizar cualquier API de tiempo de ejecución Node.js soportada por Cloudflare.

  • assert
  • AsyncLocalStorage
  • Buffer
  • Crypto
  • Diagnostics Channel
  • EventEmitter
  • path
  • process
  • Streams
  • StringDecoder
  • util

Para usar estas APIs, la página o el endpoint debe ser renderizado en el lado del servidor (no pre-renderizado) y debe utilizar la sintaxis de importación import {} from 'node:*'.

pages/api/endpoint.js
export const prerender = false;
import { Buffer } from 'node:buffer';

Además, deberás habilitar la Bandera de Compatibilidad en Cloudflare. La configuración de esta bandera puede variar según donde implementes tu sitio de Astro. Para obtener orientación detallada, consulta la documentación de Cloudflare sobre cómo habilitar la compatibilidad con Node.js.

Todos los paquetes de Cloudflare del espacio de nombres (por ejemplo, cloudflare:sockets) están permitidos para su uso. Ten en cuenta que el paquete cloudflare:sockets no funciona localmente sin utilizar el modo de desarrollo de Wrangler.

Para utilizar wrangler y ejecutar tu aplicación localmente, actualiza el script de vista previa:

package.json
"preview": "wrangler pages dev ./dist"

wrangler te proporciona acceso a Cloudflare Bindings, variables de entorno, y al objeto cf. Conseguir que la recarga en caliente o el servidor astro dev funcionen con Wrangler puede requerir una configuración personalizada. Consulta los ejemplos de la comunidad.

Actualmente, los errores que surjan durante la ejecución de tu aplicación en Wrangler no son muy útiles debido a la minificación de tu código. Para una mejor depuración, puedes agregar la configuración vite.build.minify = false a tu archivo astro.config.mjs.

astro.config.mjs
export default defineConfig({
adapter: cloudflare(),
output: 'server',
vite: {
build: {
minify: false,
},
},
});

Para obtener ayuda, visita el canal #support en Discord. ¡Nuestros amables miembros del equipo de soporte están aquí para ayudarte!

También puedes consultar nuestra Documentación sobre la integración de Astro para obtener más información sobre las integraciones.

Este paquete es mantenido por el equipo de Astro. ¡Estás invitado a abrir una issue o PR!

Más integraciones

Frameworks UI

Adaptadores SSR

Otras integraciones