🧑‍💻 Mejora la integración de archivos estáticos

Elimina el uso de `include_files!` y sustituye `include_files_service!`
por alternativas más completas ofreciadas por `static_files_service!`.
This commit is contained in:
Manuel Cillero 2025-08-16 12:15:16 +02:00
parent d810117fa6
commit 0c987f2923
10 changed files with 156 additions and 54 deletions

View file

@ -1,7 +1,7 @@
use crate::core::action::add_action;
use crate::core::extension::ExtensionRef;
use crate::core::theme::all::THEMES;
use crate::{global, include_files, include_files_service, service, trace};
use crate::{global, service, static_files_service, trace};
use parking_lot::RwLock;
@ -125,8 +125,6 @@ pub fn initialize_extensions() {
// CONFIGURA LOS SERVICIOS *************************************************************************
include_files!(assets);
pub fn configure_services(scfg: &mut service::web::ServiceConfig) {
// Sólo compila durante el desarrollo, para evitar errores 400 en la traza de eventos.
#[cfg(debug_assertions)]
@ -140,7 +138,5 @@ pub fn configure_services(scfg: &mut service::web::ServiceConfig) {
extension.configure_service(scfg);
}
include_files_service!(
scfg, assets => "/", [&global::SETTINGS.dev.pagetop_project_dir, "static"]
);
static_files_service!(scfg, [&global::SETTINGS.dev.pagetop_static_dir, assets] => "/");
}

View file

@ -13,7 +13,7 @@ include_config!(SETTINGS: Settings => [
"app.startup_banner" => "Slant",
// [dev]
"dev.pagetop_project_dir" => "",
"dev.pagetop_static_dir" => "",
// [log]
"log.enabled" => true,
@ -68,11 +68,15 @@ pub struct App {
#[derive(Debug, Deserialize)]
/// Sección `[Dev]` de la configuración. Forma parte de [`Settings`].
pub struct Dev {
/// Los archivos estáticos requeridos por `PageTop` se integran por defecto en el binario
/// ejecutable. Sin embargo, durante el desarrollo puede resultar útil servirlos desde su propio
/// directorio para evitar recompilar cada vez que se modifican. En ese caso, este ajuste debe
/// indicar la ruta absoluta al directorio raíz del proyecto.
pub pagetop_project_dir: String,
/// Directorio desde el que servir los archivos estáticos de `PageTop`.
///
/// Por defecto, los archivos se integran en el binario de la aplicación. Si aquí se indica una
/// ruta válida, ya sea absoluta o relativa al directorio del proyecto o del binario en
/// ejecución, se servirán desde el sistema de ficheros en su lugar. Esto es especialmente útil
/// en desarrollo, ya que evita recompilar el proyecto por cambios en estos archivos.
///
/// Si la cadena está vacía, se ignora este ajuste.
pub pagetop_static_dir: String,
}
#[derive(Debug, Deserialize)]

View file

@ -12,8 +12,7 @@ use crate::AutoDefault;
///
/// > **Nota**
/// > Los archivos de los iconos deben estar disponibles en el servidor web de la aplicación. Pueden
/// > incluirse en el proyecto utilizando [`include_files!`](crate::include_files) y servirse con
/// > [`include_files_service!`](crate::include_files_service).
/// > servirse usando [`static_files_service!`](crate::static_files_service).
///
/// # Ejemplo
///

View file

@ -30,8 +30,7 @@ enum Source {
///
/// > **Nota**
/// > Los archivos de los *scripts* deben estar disponibles en el servidor web de la aplicación.
/// > Pueden incluirse en el proyecto utilizando [`include_files!`](crate::include_files) y servirse
/// > con [`include_files_service!`](crate::include_files_service).
/// > Pueden servirse usando [`static_files_service!`](crate::static_files_service).
///
/// # Ejemplo
///

View file

@ -55,8 +55,7 @@ impl TargetMedia {
///
/// > **Nota**
/// > Las hojas de estilo CSS deben estar disponibles en el servidor web de la aplicación. Pueden
/// > incluirse en el proyecto utilizando [`include_files!`](crate::include_files) y servirse con
/// > [`include_files_service!`](crate::include_files_service).
/// > servirse usando [`static_files_service!`](crate::static_files_service).
///
/// # Ejemplo
///

View file

@ -103,7 +103,8 @@ pub use pagetop_macros::{builder_fn, html, main, test, AutoDefault};
pub use pagetop_statics::{resource, StaticResource};
/// Conjunto de recursos asociados a `$STATIC` en [`include_files!`](crate::include_files).
/// Contenedor para un conjunto de recursos embebidos.
#[derive(AutoDefault)]
pub struct StaticResources {
bundle: HashMap<&'static str, StaticResource>,
}

View file

@ -15,7 +15,8 @@ pub use crate::include_config;
// crate::locale
pub use crate::include_locales;
// crate::service
pub use crate::{include_files, include_files_service};
#[allow(deprecated)]
pub use crate::{include_files, include_files_service, static_files_service};
// crate::core::action
pub use crate::actions_boxed;

View file

@ -15,6 +15,9 @@ pub use pagetop_statics::ResourceFiles;
#[doc(hidden)]
pub use actix_web::test;
/// **Obsoleto desde la versión 0.3.0**: usar [`static_files_service!`](crate::static_files_service)
/// en su lugar.
///
/// Incluye en código un conjunto de recursos previamente preparado con `build.rs`.
///
/// # Formas de uso
@ -39,6 +42,7 @@ pub use actix_web::test;
///
/// include_files!(STATIC_ASSETS => assets);
/// ```
#[deprecated(since = "0.3.0", note = "Use `static_files_service!` instead")]
#[macro_export]
macro_rules! include_files {
// Forma 1: incluye un conjunto de recursos por nombre.
@ -63,6 +67,9 @@ macro_rules! include_files {
};
}
/// **Obsoleto desde la versión 0.3.0**: usar [`static_files_service!`](crate::static_files_service)
/// en su lugar.
///
/// Configura un servicio web para publicar los recursos embebidos con [`include_files!`].
///
/// El código expandido de la macro decide durante el arranque de la aplicación si debe servir los
@ -104,6 +111,7 @@ macro_rules! include_files {
/// // También desde el directorio actual de ejecución.
/// include_files_service!(cfg, assets => "/public", ["", "static"]);
/// ```
#[deprecated(since = "0.3.0", note = "Use `static_files_service!` instead")]
#[macro_export]
macro_rules! include_files_service {
( $scfg:ident, $bundle:ident => $route:expr $(, [$root:expr, $relative:expr])? ) => {{
@ -137,3 +145,114 @@ macro_rules! include_files_service {
}
}};
}
/// Configura un servicio web para publicar archivos estáticos.
///
/// La macro ofrece tres modos para configurar el servicio:
///
/// - **Sistema de ficheros o embebido** (`[$path, $bundle]`): trata de servir los archivos desde
/// `$path`; y si es una cadena vacía, no existe o no es un directorio, entonces usará el conjunto
/// de recursos `$bundle` integrado en el binario.
/// - **Sólo embebido** (`[$bundle]`): sirve siempre desde el conjunto de recursos `$bundle`
/// integrado en el binario.
/// - **Sólo sistema de ficheros** (`$path`): sin usar corchetes, sirve únicamente desde el sistema
/// de ficheros si existe; en otro caso no registra el servicio.
///
/// # Argumentos
///
/// * `$scfg` Instancia de [`ServiceConfig`](crate::service::web::ServiceConfig) donde aplicar la
/// configuración.
/// * `$path` Ruta al directorio local con los archivos estáticos.
/// * `$bundle` Nombre del conjunto de recursos que esta macro integra en el binario.
/// * `$route` Ruta URL base desde la que se servirán los archivos.
///
/// # Ejemplos
///
/// ```rust,ignore
/// use pagetop::prelude::*;
///
/// pub struct MyExtension;
///
/// impl Extension for MyExtension {
/// fn configure_service(&self, scfg: &mut service::web::ServiceConfig) {
/// // Forma 1) Sistema de ficheros o embebido.
/// static_files_service!(scfg, ["/var/www/static", assets] => "/public");
///
/// // Forma 2) Siempre embebido.
/// static_files_service!(scfg, [assets] => "/public");
///
/// // Forma 3) Sólo sistema de ficheros (no requiere `assets`).
/// static_files_service!(scfg, "/var/www/static" => "/public");
/// }
/// }
/// ```
#[macro_export]
macro_rules! static_files_service {
// Forma 1: primero intenta servir desde el sistema de ficheros; si falla, sirve embebido.
( $scfg:ident, [$path:expr, $bundle:ident] => $route:expr $(,)? ) => {{
let span = $crate::trace::debug_span!(
"Configuring static files (file system or embedded)",
mode = "fs_or_embedded",
route = $route,
);
let _ = span.in_scope(|| {
let mut serve_embedded: bool = true;
if !::std::path::Path::new(&$path).as_os_str().is_empty() {
if let Ok(absolute) = $crate::util::resolve_absolute_dir($path) {
$scfg.service($crate::service::ActixFiles::new($route, absolute));
serve_embedded = false;
}
}
if serve_embedded {
$crate::util::paste! {
mod [<static_files_ $bundle>] {
include!(concat!(env!("OUT_DIR"), "/", stringify!($bundle), ".rs"));
}
$scfg.service($crate::service::ResourceFiles::new(
$route,
[<static_files_ $bundle>]::$bundle(),
));
}
}
});
}};
// Forma 2: sirve siempre embebido.
( $scfg:ident, [$bundle:ident] => $route:expr $(,)? ) => {{
let span = $crate::trace::debug_span!(
"Configuring static files (using embedded only)",
mode = "embedded",
route = $route,
);
let _ = span.in_scope(|| {
$crate::util::paste! {
mod [<static_files_ $bundle>] {
include!(concat!(env!("OUT_DIR"), "/", stringify!($bundle), ".rs"));
}
$scfg.service($crate::service::ResourceFiles::new(
$route,
[<static_files_ $bundle>]::$bundle(),
));
}
});
}};
// Forma 3: intenta servir desde el sistema de ficheros.
( $scfg:ident, $path:expr => $route:expr $(,)? ) => {{
let span = $crate::trace::debug_span!(
"Configuring static files (file system only)",
mode = "fs",
route = $route,
);
let _ = span.in_scope(|| match $crate::util::resolve_absolute_dir($path) {
Ok(absolute) => {
$scfg.service($crate::service::ActixFiles::new($route, absolute));
}
Err(e) => {
$crate::trace::warn!(
"Static dir not found or invalid for route `{}`: {:?} ({e})",
$route,
$path,
);
}
});
}};
}