Mejora gestión de archivos estáticos en el binario

This commit is contained in:
Manuel Cillero 2022-08-05 00:05:26 +02:00
parent c0a269f009
commit 9997a6b0b1
14 changed files with 163 additions and 72 deletions

View file

@ -19,4 +19,4 @@ static-files = "0.2.3"
maud = { git = "https://github.com/lambda-fairy/maud", rev = "e6787cd6" } maud = { git = "https://github.com/lambda-fairy/maud", rev = "e6787cd6" }
[build-dependencies] [build-dependencies]
static-files = "0.2.3" pagetop = { path = "../pagetop" }

View file

@ -1,17 +1,5 @@
use static_files::resource_dir; use pagetop::util::bundle_resources;
use std::env;
use std::path::Path;
fn main() -> std::io::Result<()> { fn main() -> std::io::Result<()> {
build_resource_dir("./static", "mdbook") bundle_resources("./static", "mdbook", None)
}
fn build_resource_dir(dir: &str, name: &str) -> std::io::Result<()> {
let mut resource = resource_dir(dir);
resource.with_generated_filename(
Path::new(env::var("OUT_DIR").unwrap().as_str()).join(format!("{}.rs", name)),
);
resource.with_module_name(format!("resources_{}", name));
resource.build()
} }

View file

@ -1,11 +1,11 @@
use pagetop::prelude::*; use pagetop::prelude::*;
pub mod util;
pub_const_handler!(MODULE_MDBOOK); pub_const_handler!(MODULE_MDBOOK);
include!(concat!(env!("OUT_DIR"), "/mdbook.rs")); include!(concat!(env!("OUT_DIR"), "/mdbook.rs"));
pub type BookMapResources = std::collections::HashMap<&'static str, static_files::Resource>;
pub struct MdBook; pub struct MdBook;
impl ModuleTrait for MdBook { impl ModuleTrait for MdBook {
@ -15,14 +15,14 @@ impl ModuleTrait for MdBook {
} }
impl MdBook { impl MdBook {
pub fn configure_mdbook_common(cfg: &mut app::web::ServiceConfig) { pub fn configure_service_for_common_resources(cfg: &mut app::web::ServiceConfig) {
theme_static_files!(cfg, "/mdbook/static"); configure_service_for_static_files!(cfg, "/mdbook/static", bundle_mdbook);
} }
pub fn configure_mdbook_service( pub fn configure_service_for_mdbook(
cfg: &mut app::web::ServiceConfig, cfg: &mut app::web::ServiceConfig,
mdbook_path: &'static str, mdbook_path: &'static str,
mdbook_map: &'static BookMapResources, mdbook_map: &'static HashMapResources,
) { ) {
let path = mdbook_path.trim_end_matches('/'); let path = mdbook_path.trim_end_matches('/');
cfg.service( cfg.service(
@ -46,7 +46,7 @@ impl MdBook {
async fn mdbook_page( async fn mdbook_page(
request: app::HttpRequest, request: app::HttpRequest,
mdbook_path: &'static str, mdbook_path: &'static str,
mdbook_map: &'static BookMapResources, mdbook_map: &'static HashMapResources,
) -> ResultPage<Markup, FatalError> { ) -> ResultPage<Markup, FatalError> {
let path_len = mdbook_path.len() + 1; let path_len = mdbook_path.len() + 1;
if let Some(content) = mdbook_map.get(&request.path()[path_len..]) { if let Some(content) = mdbook_map.get(&request.path()[path_len..]) {
@ -115,7 +115,7 @@ async fn mdbook_page(
async fn mdbook_resource( async fn mdbook_resource(
request: app::HttpRequest, request: app::HttpRequest,
mdbook_path: &'static str, mdbook_path: &'static str,
mdbook_map: &'static BookMapResources, mdbook_map: &'static HashMapResources,
) -> app::HttpResponse { ) -> app::HttpResponse {
let path_len = mdbook_path.len() + 1; let path_len = mdbook_path.len() + 1;
// From https://github.com/kilork/actix-web-static-files/blob/master/src/resource_files.rs, see // From https://github.com/kilork/actix-web-static-files/blob/master/src/resource_files.rs, see

View file

@ -0,0 +1,21 @@
use std::path::Path;
pub fn except_mdbook_common_resources(p: &Path) -> bool {
match p.to_str() {
Some("ayu-highlight.css") => false,
Some("highlight.css") => false,
Some("tomorrow-niht.css") => false,
_ => {
if let Some(parent) = p.parent() {
match parent.to_str() {
Some("/css") => false,
Some("/FontAwesome") => false,
Some("/fonts") => false,
_ => true,
}
} else {
true
}
}
}
}

View file

@ -1,20 +1,19 @@
use static_files::resource_dir;
use std::env;
use std::path::Path; use std::path::Path;
fn main() -> std::io::Result<()> { fn main() -> std::io::Result<()> {
build_resource_dir("./static/theme", "theme")?; bundle_resources("./static/theme", "theme")?;
build_resource_dir("./static/aliner", "aliner")?; bundle_resources("./static/aliner", "aliner")?;
build_resource_dir("./static/bootsier", "bootsier")?; bundle_resources("./static/bootsier", "bootsier")?;
build_resource_dir("./static/bulmix", "bulmix") bundle_resources("./static/bulmix", "bulmix")
} }
fn build_resource_dir(dir: &str, name: &str) -> std::io::Result<()> { /// This function is a simplified version of pagetop::util::bundle_resources().
let mut resource = resource_dir(dir); pub fn bundle_resources(from_dir: &str, with_name: &str) -> std::io::Result<()> {
resource.with_generated_filename( let mut r = static_files::resource_dir(from_dir);
Path::new(env::var("OUT_DIR").unwrap().as_str()).join(format!("{}.rs", name)), r.with_generated_filename(
Path::new(std::env::var("OUT_DIR").unwrap().as_str()).join(format!("{}.rs", with_name)),
); );
resource.with_module_name(format!("resources_{}", name)); r.with_module_name(format!("resources_{}", with_name));
resource.build() r.with_generated_fn(format!("bundle_{}", with_name));
r.build()
} }

View file

@ -12,7 +12,7 @@ impl ThemeTrait for Aliner {
} }
fn configure_service(&self, cfg: &mut app::web::ServiceConfig) { fn configure_service(&self, cfg: &mut app::web::ServiceConfig) {
theme_static_files!(cfg, "/aliner"); configure_service_for_static_files!(cfg, "/aliner", bundle_aliner);
} }
fn before_render_page(&self, page: &mut Page) { fn before_render_page(&self, page: &mut Page) {

View file

@ -14,7 +14,7 @@ impl ThemeTrait for Bootsier {
} }
fn configure_service(&self, cfg: &mut app::web::ServiceConfig) { fn configure_service(&self, cfg: &mut app::web::ServiceConfig) {
theme_static_files!(cfg, "/bootsier"); configure_service_for_static_files!(cfg, "/bootsier", bundle_bootsier);
} }
fn before_render_page(&self, page: &mut Page) { fn before_render_page(&self, page: &mut Page) {

View file

@ -12,7 +12,7 @@ impl ThemeTrait for Bulmix {
} }
fn configure_service(&self, cfg: &mut app::web::ServiceConfig) { fn configure_service(&self, cfg: &mut app::web::ServiceConfig) {
theme_static_files!(cfg, "/bulmix"); configure_service_for_static_files!(cfg, "/bulmix", bundle_bulmix);
} }
fn before_render_page(&self, page: &mut Page) { fn before_render_page(&self, page: &mut Page) {

View file

@ -1,5 +1,5 @@
use super::ThemeStaticRef; use super::ThemeStaticRef;
use crate::{app, base, theme_static_files, trace, LazyStatic}; use crate::{app, base, configure_service_for_static_files, trace, LazyStatic};
use std::sync::RwLock; use std::sync::RwLock;
@ -41,7 +41,7 @@ pub fn theme_by_single_name(single_name: &str) -> Option<ThemeStaticRef> {
} }
pub fn configure_services(cfg: &mut app::web::ServiceConfig) { pub fn configure_services(cfg: &mut app::web::ServiceConfig) {
theme_static_files!(cfg, "/theme"); configure_service_for_static_files!(cfg, "/theme", bundle_theme);
for t in THEMES.read().unwrap().iter() { for t in THEMES.read().unwrap().iter() {
t.configure_service(cfg); t.configure_service(cfg);

View file

@ -1,9 +1,9 @@
//! Re-exporta recursos comunes.
// Global macros and helpers. // Global macros and helpers.
pub use crate::util; pub use crate::util;
pub use crate::util::Handler; pub use crate::util::{Handler, HashMapResources};
pub use crate::{args, concat_string, pub_const_handler, theme_static_files, LazyStatic}; pub use crate::{
args, concat_string, configure_service_for_static_files, pub_const_handler, LazyStatic,
};
pub use crate::config::SETTINGS; pub use crate::config::SETTINGS;

View file

@ -1,3 +1,90 @@
pub use static_files::Resource as StaticResource;
use std::path::Path;
pub type HashMapResources = std::collections::HashMap<&'static str, StaticResource>;
/// This function uses the [static_files](https://docs.rs/static-files/latest/static_files/) library
/// to embed at compile time a bundle of static files in your binary.
///
/// Just create the folder with static resources in your project (for example `static`):
///
/// ```bash
/// cd project_dir
/// mkdir static
/// echo "Hello, world" > static/hello
/// ```
///
/// Add to `Cargo.toml` the required dependencies:
///
/// ```toml
/// [dependencies]
/// pagetop = { ... }
/// static-files = "0.2.3"
///
/// [build-dependencies]
/// pagetop = { ... }
/// ```
///
/// Add `build.rs` with call to bundle resources:
///
/// ```rust#ignore
/// use pagetop::util::bundle_resources;
///
/// fn main() -> std::io::Result<()> {
/// bundle_resources("./static", "guides", None)
/// }
/// ```
///
/// This will create the resources file "guides.rs" in the standard output directory from files
/// located at "./static" folder.
///
/// Optionally, you can also pass a function to filter the files in the "./static" folder that
/// should be included in the resources file:
///
/// ```rust#ignore
/// use pagetop::util::bundle_resources;
///
/// fn main() -> std::io::Result<()> {
/// bundle_resources("./static", "guides", Some(except_css_dir))
/// }
///
/// fn except_css_dir(p: &Path) -> bool {
/// if let Some(parent) = p.parent() {
/// ! matches!(parent.to_str(), Some("/css"))
/// }
/// true
/// }
/// ```
///
/// Finally, a module called "resources_guides" will be compiled with your project. And the function
/// to embed the generated HashMap resources collection in your code will be "bundle_guides":
///
/// ```rust#ignore
/// use pagetop::prelude::*;
///
/// include!(concat!(env!("OUT_DIR"), "/guides.rs"));
/// static GUIDES: LazyStatic<HashMapResources> = LazyStatic::new(bundle_guides);
/// ```
///
/// You can build more than one resources file to compile with your project.
pub fn bundle_resources(
from_dir: &str,
with_name: &str,
filtering: Option<fn(p: &Path) -> bool>,
) -> std::io::Result<()> {
let mut r = static_files::resource_dir(from_dir);
r.with_generated_filename(
Path::new(std::env::var("OUT_DIR").unwrap().as_str()).join(format!("{}.rs", with_name)),
);
r.with_module_name(format!("resources_{}", with_name));
r.with_generated_fn(format!("bundle_{}", with_name));
if let Some(filter_files) = filtering {
r.with_filter(filter_files);
}
r.build()
}
pub type Handler = u64; pub type Handler = u64;
// https://stackoverflow.com/a/71464396 // https://stackoverflow.com/a/71464396
@ -60,7 +147,7 @@ pub fn single_type_name<T: ?Sized>() -> &'static str {
#[macro_export] #[macro_export]
/// Macro para construir grupos de pares clave-valor. /// Macro para construir grupos de pares clave-valor.
/// ///
/// ``` /// ```rust#ignore
/// let args = args![ /// let args = args![
/// "userName" => "Roberto", /// "userName" => "Roberto",
/// "photoCount" => 3, /// "photoCount" => 3,
@ -78,11 +165,11 @@ macro_rules! args {
} }
#[macro_export] #[macro_export]
macro_rules! theme_static_files { macro_rules! configure_service_for_static_files {
( $cfg:ident, $dir:expr ) => {{ ( $cfg:ident, $dir:expr, $embed:ident ) => {{
let static_files = &$crate::config::SETTINGS.dev.static_files; let static_files = &$crate::config::SETTINGS.dev.static_files;
if static_files.is_empty() { if static_files.is_empty() {
$cfg.service($crate::app::ResourceFiles::new($dir, generate())); $cfg.service($crate::app::ResourceFiles::new($dir, $embed()));
} else { } else {
$cfg.service( $cfg.service(
$crate::app::ActixFiles::new($dir, $crate::concat_string!(static_files, $dir)) $crate::app::ActixFiles::new($dir, $crate::concat_string!(static_files, $dir))

View file

@ -23,4 +23,5 @@ pagetop-mdbook = { path = "../pagetop-mdbook" }
maud = { git = "https://github.com/lambda-fairy/maud", rev = "e6787cd6" } maud = { git = "https://github.com/lambda-fairy/maud", rev = "e6787cd6" }
[build-dependencies] [build-dependencies]
static-files = "0.2.3" pagetop = { path = "../pagetop" }
pagetop-mdbook = { path = "../pagetop-mdbook" }

View file

@ -1,19 +1,15 @@
use static_files::resource_dir; use pagetop::util::bundle_resources;
use pagetop_mdbook::util::except_mdbook_common_resources;
use std::env;
use std::path::Path;
fn main() -> std::io::Result<()> { fn main() -> std::io::Result<()> {
build_resource_dir("./static/doc/en", "guides_en")?; bundle_resources(
build_resource_dir("./static/doc/es", "guias_es") "./static/doc/en",
} "guides_en",
Some(except_mdbook_common_resources),
fn build_resource_dir(dir: &str, name: &str) -> std::io::Result<()> { )?;
let mut resource = resource_dir(dir); bundle_resources(
resource.with_generated_filename( "./static/doc/es",
Path::new(env::var("OUT_DIR").unwrap().as_str()).join(format!("{}.rs", name)), "guias_es",
); Some(except_mdbook_common_resources),
resource.with_module_name(format!("resources_{}", name)); )
resource.with_generated_fn(name);
resource.build()
} }

View file

@ -1,14 +1,13 @@
use pagetop::prelude::*; use pagetop::prelude::*;
use pagetop_mdbook::BookMapResources;
use pagetop_mdbook::MdBook; use pagetop_mdbook::MdBook;
pub_const_handler!(APP_PAGETOP_WEBSITE); pub_const_handler!(APP_PAGETOP_WEBSITE);
include!(concat!(env!("OUT_DIR"), "/guides_en.rs")); include!(concat!(env!("OUT_DIR"), "/guides_en.rs"));
static GUIDES_EN: LazyStatic<BookMapResources> = LazyStatic::new(guides_en); static GUIDES_EN: LazyStatic<HashMapResources> = LazyStatic::new(bundle_guides_en);
include!(concat!(env!("OUT_DIR"), "/guias_es.rs")); include!(concat!(env!("OUT_DIR"), "/guias_es.rs"));
static GUIAS_ES: LazyStatic<BookMapResources> = LazyStatic::new(guias_es); static GUIAS_ES: LazyStatic<HashMapResources> = LazyStatic::new(bundle_guias_es);
struct PageTopWebSite; struct PageTopWebSite;
@ -22,9 +21,9 @@ impl ModuleTrait for PageTopWebSite {
} }
fn configure_service(&self, cfg: &mut app::web::ServiceConfig) { fn configure_service(&self, cfg: &mut app::web::ServiceConfig) {
MdBook::configure_mdbook_common(cfg); MdBook::configure_service_for_common_resources(cfg);
MdBook::configure_mdbook_service(cfg, "/doc/en", &GUIDES_EN); MdBook::configure_service_for_mdbook(cfg, "/doc/en", &GUIDES_EN);
MdBook::configure_mdbook_service(cfg, "/doc/es", &GUIAS_ES); MdBook::configure_service_for_mdbook(cfg, "/doc/es", &GUIAS_ES);
} }
} }