package lazyassets ¶
import "golazy.dev/lazyassets"
Constants ¶
const LazyDevAssetsPath ¶
const LazyDevAssetsPath = "/assets"
Functions ¶
func RegisterLazyDevHandlers ¶
RegisterLazyDevHandlers registers asset inventory endpoints.
func RegisterLazyDevHandlers(controlPlane *lazycontrolplane.ControlPlane, registry *Registry)
Types ¶
type Asset ¶
Asset describes one registered asset as it appears in a Manifest.
type Asset struct {
// Path is the logical public path, for example /styles.css.
Path string `json:"path"`
// Permanent is the content-hashed public path, for example
// /styles-<hash>.css. It is empty for development-mode or ignored assets.
Permanent string `json:"permanent,omitempty"`
// ContentType is the MIME type sent by Handler and written by Upload.
ContentType string `json:"content_type,omitempty"`
// Size is the served byte length, or -1 when development mode reads the
// file each time and the size is not fixed in the manifest.
Size int64 `json:"size"`
// Hash is the full SHA-256 hex digest of the final served bytes.
Hash string `json:"hash,omitempty"`
// ETag is the strong ETag for the final served bytes.
ETag string `json:"etag,omitempty"`
// Integrity is the subresource-integrity value for the final served bytes.
Integrity string `json:"integrity,omitempty"`
// Source identifies the source file or generator, when supplied.
Source string `json:"source,omitempty"`
// Generated is true for assets registered from in-memory/generated bytes.
Generated bool `json:"generated,omitempty"`
// Ignored is true for oversized assets that are served by logical path but
// skipped by hashing, permanent URL generation, and rewriting.
Ignored bool `json:"ignored,omitempty"`
// contains filtered or unexported fields
}
func (a *Asset) Open ¶
Open opens the asset content that Handler, Upload, and Unpack serve or write.
func (a *Asset) Open() (io.ReadCloser, error)
type AssetOption ¶
AssetOption configures Add and AddReader.
type AssetOption func(*assetOptions)
func AssetSource ¶
AssetSource records name as the source for one registered asset.
func AssetSource(name string) AssetOption
func ContentType ¶
ContentType sets the asset MIME type instead of inferring it from the path and content.
func ContentType(contentType string) AssetOption
func ReplaceAsset ¶
ReplaceAsset allows Add or AddReader to replace a previously registered asset with the same logical path.
func ReplaceAsset() AssetOption
type CachePolicy ¶
CachePolicy is the literal Cache-Control value used when serving or uploading logical and permanent asset paths.
type CachePolicy string
type Manifest ¶
Manifest is a snapshot of all registered assets and their computed metadata.
type Manifest struct {
Assets []Asset `json:"assets"`
}
type OpenFunc ¶
OpenFunc opens an asset stream for AddReader or filesystem-backed records.
type OpenFunc func() (io.ReadCloser, error)
type Option ¶
Option configures New.
type Option func(*Options)
func WithBaseURL ¶
WithBaseURL makes helpers return absolute asset URLs while keeping request routing and storage keys path-based.
func WithBaseURL(baseURL string) Option
func WithCSSURLRewrite ¶
WithCSSURLRewrite enables or disables rewriting local CSS url(...) references to permanent asset URLs.
func WithCSSURLRewrite(enabled bool) Option
func WithCachePolicies ¶
WithCachePolicies sets Cache-Control values for logical and permanent paths.
func WithCachePolicies(logical, permanent CachePolicy) Option
func WithDevelopmentMode ¶
WithDevelopmentMode serves logical asset paths directly without permanent hashed URLs, cache headers, ETags, integrity values, or CSS URL rewriting.
func WithDevelopmentMode(enabled bool) Option
func WithHashLength ¶
WithHashLength sets the number of hexadecimal hash characters inserted into permanent paths.
func WithHashLength(length int) Option
func WithMaxAssetSize ¶
WithMaxAssetSize sets the largest asset read into the fingerprinting pipeline.
func WithMaxAssetSize(size int64) Option
func WithOversizePolicy ¶
WithOversizePolicy sets the behavior for assets larger than MaxAssetSize.
func WithOversizePolicy(policy OversizePolicy) Option
func WithURLPrefix ¶
WithURLPrefix mounts assets below prefix.
func WithURLPrefix(prefix string) Option
type Options ¶
Options configures a Registry.
type Options struct {
// URLPrefix mounts registered assets below a path prefix. With /assets, an
// asset added as /app.js is served and reported as /assets/app.js.
URLPrefix string
// MaxAssetSize limits assets that are read into the fingerprinting pipeline.
// Negative values disable the limit.
MaxAssetSize int64
// OversizePolicy selects behavior for assets larger than MaxAssetSize.
OversizePolicy OversizePolicy
// HashLength is the number of hexadecimal hash characters inserted into
// permanent paths.
HashLength int
// LogicalCache is sent for logical paths such as /styles.css.
LogicalCache CachePolicy
// PermanentCache is sent for permanent paths such as /styles-<hash>.css.
PermanentCache CachePolicy
// RewriteCSSURLs rewrites local CSS url(...) references to permanent paths
// for registered target assets.
RewriteCSSURLs bool
// BaseURL makes helpers and rewritten CSS/importmap URLs absolute without
// changing the request paths that Handler serves or Upload writes.
BaseURL string
// Development disables permanent paths, cache headers, ETags, integrity
// values, and CSS rewriting so filesystem assets can be served fresh.
Development bool
}
type OversizePolicy ¶
OversizePolicy controls how disk or generated assets larger than MaxAssetSize participate in hashing, rewriting, serving, and export.
type OversizePolicy int
type Registry ¶
Registry owns the registered asset index.
It maps logical request paths and content-hashed permanent request paths to the same Asset records. The manifest is derived from the registered records; callers do not need to load or create one before serving.
type Registry struct {
// contains filtered or unexported fields
}
func New ¶
New creates an empty Registry.
By default, logical paths are revalidation-friendly, permanent paths are immutable, CSS local URLs are rewritten, and permanent paths use a 12 character hash prefix.
func New(options ...Option) *Registry
func (r *Registry) Add ¶
Add registers an in-memory asset at path.
Generated assets are fingerprinted like filesystem assets and appear in the manifest with Generated set. The content slice is copied before registration.
func (r *Registry) Add(path string, content []byte, options ...AssetOption) error
func (r *Registry) AddFS ¶
AddFS registers every file in files under its slash-separated path.
AddFS computes permanent paths and manifest metadata immediately unless development mode or the oversize policy keeps an asset out of the fingerprinting pipeline. Directories are skipped.
func (r *Registry) AddFS(files fs.FS, options ...SourceOption) error
func (r *Registry) AddReader ¶
AddReader registers an asset opened on demand by open.
In production mode AddReader reads the content during registration so it can compute the hash, ETag, integrity value, permanent path, and CSS rewrites. In development mode it keeps open and reads the asset for each request.
func (r *Registry) AddReader(path string, open OpenFunc, options ...AssetOption) error
func (r *Registry) Empty ¶
Empty reports whether the Registry has no registered assets.
func (r *Registry) Empty() bool
func (r *Registry) Handler ¶
Handler serves registered assets and falls through to next for misses.
Requests are matched against logical paths such as /styles.css and permanent paths such as /styles-<hash>.css. Requests for / and paths ending in / look for index.html below that directory. Only GET and HEAD are served; other methods for known asset paths return 405 with Allow: GET, HEAD. Unknown paths are passed to next.
The original logical files remain available through Handler unless an asset was skipped entirely by OversizeSkipServing. Permanent paths are generated when assets are added; no separate manifest creation step is required.
func (r *Registry) Handler(next http.Handler) http.Handler
func (r *Registry) Helpers ¶
Helpers returns lazyview-compatible template helpers for registered assets.
lazyapp calls Helpers during startup and adds the returned functions to lazyview. Templates then use helpers such as asset_path, stylesheet, importmap, asset_integrity, and the compatibility alias permalink.
func (r *Registry) Helpers() map[string]any
func (r *Registry) Integrity ¶
Integrity returns the subresource-integrity value for assetPath.
Development-mode and ignored oversized assets do not have integrity metadata, so Integrity returns an empty string for those registered assets.
func (r *Registry) Integrity(assetPath string) (string, error)
func (r *Registry) Manifest ¶
Manifest returns a snapshot of the current registered assets.
The manifest is computed from assets already added to the Registry; callers do not need to create or load it before calling Handler, Path, Upload, or Unpack.
func (r *Registry) Manifest() Manifest
func (r *Registry) MustPath ¶
MustPath is like Path, but panics on error.
func (r *Registry) MustPath(assetPath string) string
func (r *Registry) Path ¶
Path returns the URL to use for assetPath in HTML or generated output.
It returns the permanent content-hashed path when the asset has one. In development mode and for ignored oversized assets, it returns the logical path. WithBaseURL makes the returned URL absolute.
func (r *Registry) Path(assetPath string) (string, error)
func (r *Registry) ServeHTTP ¶
ServeHTTP serves the Registry as a standalone http.Handler.
func (r *Registry) ServeHTTP(w http.ResponseWriter, req *http.Request)
func (r *Registry) Unpack ¶
Unpack writes registered assets and manifest.json into dir.
By default it writes both logical and permanent asset files. The manifest is always written and is derived from the Registry's current asset records.
func (r *Registry) Unpack(dir string, options ...UnpackOption) error
func (r *Registry) Upload ¶
Upload writes registered assets to object storage.
The default mode writes only permanent content-hashed paths plus manifest.json, which is the usual shape for CDN or static-file ingress deployments.
func (r *Registry) Upload(ctx context.Context, storage lazystorage.Writer, options ...UploadOption) error
type Source ¶
Source registers assets in a Registry.
Generated asset packages can implement Source so lazyapp or custom startup code can add generated files to the same Registry as filesystem assets.
type Source interface {
Assets(*Registry) error
}
type SourceFunc ¶
SourceFunc adapts a function into a Source.
type SourceFunc func(*Registry) error
func (fn SourceFunc) Assets ¶
Assets calls fn(registry).
func (fn SourceFunc) Assets(registry *Registry) error
type SourceOption ¶
SourceOption configures AddFS.
type SourceOption func(*sourceOptions)
func Replace ¶
Replace allows AddFS to replace previously registered assets with the same logical path.
func Replace() SourceOption
func SourceName ¶
SourceName records name as the source for assets registered from AddFS.
func SourceName(name string) SourceOption
type UnpackMode ¶
UnpackMode selects which asset path forms Unpack and Upload write.
type UnpackMode int
type UnpackOption ¶
UnpackOption configures Unpack.
type UnpackOption func(*unpackOptions)
func WithUnpackMode ¶
WithUnpackMode selects which asset path forms Unpack writes.
func WithUnpackMode(mode UnpackMode) UnpackOption
type UploadOption ¶
type UploadOption func(*uploadOptions)
func WithUploadMode ¶
WithUploadMode selects which asset paths are written to storage.
func WithUploadMode(mode UnpackMode) UploadOption
func WithUploadPrefix ¶
WithUploadPrefix writes assets below prefix in the destination storage.
func WithUploadPrefix(prefix string) UploadOption
func WithoutUploadManifest ¶
WithoutUploadManifest disables writing manifest.json to storage.
func WithoutUploadManifest() UploadOption
Package lazyassets registers, fingerprints, serves, and exports application assets.
In a GoLazy application, lazyapp registers Public files and generated asset sources into one Registry, installs view helpers such as asset_path and stylesheet, and serves registered files as the final public fallback. lazyapp passes Registry.Helpers to lazyview so templates can render the final asset URLs without naming lazyassets directly.
The package is also independently usable for static file serving or deploy preparation:
registry := lazyassets.New() err := registry.AddFS(os.DirFS("public")) if err != nil { return err } http.Handle("/", registry.Handler(nil))Registered assets keep a logical path, such as /styles.css, and usually get a permanent content-hashed path, such as /styles-2c26b46b68ff.css. Handler serves both paths. View helpers return the permanent path when one exists, so browser caches can keep immutable assets while templates still use stable source names.
A Registry builds its manifest as assets are added. Callers do not create a manifest first: Add, AddReader, and AddFS compute hashes, ETags, integrity values, permanent paths, and CSS URL rewrites automatically. CSS url(...) references that point at other registered local assets are rewritten to the target asset's permanent path; remote URLs, data URLs, fragments, and missing assets are left unchanged.
For deployment, Upload writes registered files through lazystorage and Unpack writes them to a local directory. Both can choose logical paths, permanent paths, or both.