pub struct IrModules<A> { /* private fields */ }Expand description
The page modules, loaded at start by the strict loader, and in a debug build reread when the build’s watch mode rewrites one.
load_ir_modules_strict hands the application its modules once, so a
page edited under forma-build --watch showed its change only after a
server restart. An application that holds its modules here instead asks
for a route’s module per request, with IrModules::get:
- In a release build
getis a map lookup. Nothing is watched or checked: the modules are the ones embedded in the binary, which cannot change. - In a debug build (
cfg(debug_assertions))getfirst rereads the manifest’s entry for the route and the module’s file, and when the bytes differ from the module it holds, loads the new one through the same check as start (IrModule::parse, the strict loader’s). A module that fails it keeps the previous one, and the failure is logged once per distinct file, as atracingwarning carrying itsLOAD-1xxcode; the next good write replaces it. A route the manifest starts naming after start is loaded on its firstget; a route the manifest stops naming keeps its last module.
Why per request, and why debug builds: in a debug build rust-embed reads
every file from disk on each call, so rereading the manifest and the module
costs two small reads and a comparison, and the next request sees the
build’s last write, with no watcher thread, no file-watching dependency
and no path for forma-server to know beyond the Embed type. The watch
mode publishes a module by rename and only when its bytes change, so a read
never sees half a file and an unchanged module is never reloaded. In a
release build rust-embed serves the bytes compiled in, so there is nothing
to reread, and the check is not compiled: the switch is rust-embed’s own.
(An application that enables rust-embed’s debug-embed feature has its
files compiled into debug builds too; get then finds nothing changed.)
“Debug build” here means forma-server compiled with debug assertions
(cfg(debug_assertions)), not a profile’s name. Cargo’s default release
profile turns them off, so a default release binary reads nothing per
request. A profile that sets debug-assertions = true, for the whole
build or for forma-server alone ([profile.release.package.forma-server]),
compiles the check into what it calls a release binary: each get then
rereads the files, from the build folder on disk (rust-embed reads from
disk under the same switch), or, with debug-embed, from the embedded
bytes at the cost of a lock and a comparison. Keep debug assertions off in
the profile you deploy.
The strict loader’s render_modes map has no counterpart here: a route is
server-rendered exactly when get(route) returns a module, and a route
without one (ssr: false) is served with
render_browser_shell.
use forma_server::{assets, IrModules, PageConfig};
use std::sync::Arc;
// At start, before the port binds: refuse to start on any error.
fn start<Assets: rust_embed::Embed>() -> Result<Arc<IrModules<Assets>>, String> {
let manifest = assets::try_load_manifest::<Assets>()?;
let modules = IrModules::<Assets>::load(&manifest).map_err(|errors| {
errors.iter().map(|e| e.to_string()).collect::<Vec<_>>().join("; ")
})?;
Ok(Arc::new(modules))
}
// Per request: hold the route's module for the render.
fn module<Assets: rust_embed::Embed>(modules: &IrModules<Assets>) -> Option<Arc<forma_ir::IrModule>> {
modules.get("/") // then `ir_module: module.as_deref()` in the PageConfig
}Verified by: crates/forma-server/tests/dev_reload.rs > “an_edited_page_is_served_on_the_next_request_and_a_broken_edit_keeps_the_previous_page” Verified by: crates/forma-server/src/ir_compat.rs > “a_release_build_reads_nothing_per_request_and_a_debug_build_rereads”
Implementations§
Source§impl<A: Embed> IrModules<A>
impl<A: Embed> IrModules<A>
Sourcepub fn load(manifest: &AssetManifest) -> Result<Self, Vec<IrLoadError>>
pub fn load(manifest: &AssetManifest) -> Result<Self, Vec<IrLoadError>>
Load every module the manifest declares, through the strict loader:
the modules, or every failure, as load_ir_modules_strict returns
them. Call it at start and refuse to start on Err.
§Errors
One IrLoadError per module that is not embedded or fails its
check, naming route, file and code.