# NAME HTML::DeferableCSS - Simplify management of stylesheets in your HTML # VERSION version v0.3.0 # SYNOPSIS ```perl use HTML::DeferableCSS; my $css = HTML::DeferableCSS->new( css_root => '/var/www/css', url_base_path => '/css', inline_max => 512, aliases => { reset => 1, jqui => 'jquery-ui', site => 'style', }, cdn => { jqui => '//cdn.example.com/jquery-ui.min.css', }, ); $css->check or die "Something is wrong"; ... print $css->deferred_link_html( qw[ jqui site ] ); ``` # DESCRIPTION This is an experimental module for generating HTML-snippets for deferable stylesheets. This allows the stylesheets to be loaded asynchronously, allowing the page to be rendered faster. Ideally, this would be a simple matter of changing stylesheet links to something like ``` ``` but this is not well supported by all web browsers. So a web page needs some [JavaScript](https://github.com/filamentgroup/loadCSS) to handle this, as well as a `noscript` block as a fallback. This module allows you to simplify the management of stylesheets for a web application, from development to production by - declaring all stylesheets used by your web application; - specifying remote aliases for stylesheets, e.g. from a CDN; - enable or disable the use of minified stylesheets; - switch between local copies of stylesheets or CDN versions; - automatically inline small stylesheets; - use deferred-loading stylesheets, which requires embedding JavaScript code as a workaround for web browsers that do not support these natively. # ATTRIBUTES ## aliases This is a required hash reference of names and their relative filenames to ["css\_root"](#css_root). It is recommended that the `.css` and `.min.css` suffixes be omitted. If the name is the same as the filename (without the extension) than you can simply use `1`. (Likewise, an empty string or `0` disables the alias: ```perl my $css = HTML::DeferableCSS->new( aliases => { reset => 1, gone => 0, # using "gone" will throw an error one => "1.css", # } ... ); ``` If all names are the same as their filenames, then an array reference can be used: ```perl my $css = HTML::DeferableCSS->new( aliases => [ qw( foo bar } ], ... ); ``` Absolute paths cannot be used. You may specify URLs instead of files, but this is not recommended, except for cases when the files are not available locally. ## css\_root This is the required root directory where all stylesheets can be found. ## url\_base\_path This is the URL prefix for stylesheets. It can be a full URL prefix. ## prefer\_min If true (default), then a file with the `.min.css` suffix will be preferred, if it exists in the same directory. Note that this does not do any minification. You will need separate tools for that. ## css\_files This is a hash reference used internally to translate ["aliases"](#aliases) into the actual files or URLs. If files cannot be found, then it will throw an error. (See ["check"](#check)). ## cdn\_links This is a hash reference of ["aliases"](#aliases) to URLs. (Only one URL per alias is supported.) When ["use\_cdn\_links"](#use_cdn_links) is true, then these URLs will be used instead of local versions. ## has\_cdn\_links This is true when there are ["cdn\_links"](#cdn_links). ## use\_cdn\_links When true, this will prefer CDN URLs instead of local files. ## inline\_max This specifies the maximum size of an file to inline. Local files under the size will be inlined using the ["link\_or\_inline\_html"](#link_or_inline_html) or ["deferred\_link\_html"](#deferred_link_html) methods. Setting this to 0 disables the use of inline links, unless ["inline\_html"](#inline_html) is called explicitly. ## defer\_css True by default. This is used by ["deferred\_link\_html"](#deferred_link_html) to determine whether to emit code for deferred stylesheets. ## include\_noscript When true, a `noscript` element will be included with non-deffered links. This defaults to the same value as ["defer\_css"](#defer_css). ## preload\_script This is the pathname of the `cssrelpreload.js` file that will be embedded in the resulting code. The script comes from [https://github.com/filamentgroup/loadCSS](https://github.com/filamentgroup/loadCSS). You do not need to modify this unless you want to use a different script from the one included with this module. ## link\_template This is a code reference for a subroutine that returns a stylesheet link. ## preload\_template This is a code reference for a subroutine that returns a stylesheet preload link. ## asset\_id This is an optional static asset id to append to local links. It may refer to a version number or commit-id, for example. This is useful to ensure that changes to stylesheets are picked up by web browsers that would otherwise use cached copies of older versions of files. ## has\_asset\_id True if there is an ["asset\_id"](#asset_id). ## log This is a code reference for logging errors and warnings: ```perl $css->log->( $level => $message ); ``` By default, this is a wrapper around [Carp](https://metacpan.org/pod/Carp) that dies when the level is "error", and emits a warning for everything else. You can override this so that errors are treated as warnings, ```perl log => sub { warn $_[1] }, ``` or that warnings are fatal, ```perl log => sub { die $_[1] }, ``` or even integrate this with your own logging system: ```perl log => sub { $logger->log(@_) }, ``` # METHODS ## check This method instantiates lazy attributes and performs some minimal checks on the data. (This should be called instead of ["css\_files"](#css_files).) It will throw an error or return false (depending on ["log"](#log)) if there is something wrong. This was added in v0.3.0. ## href ```perl my $href = $css->href( $alias ); ``` This returns this URL for an alias. ## link\_html ```perl my $html = $css->link_html( $alias ); ``` This returns the link HTML markup for the stylesheet referred to by `$alias`. ## inline\_html ```perl my $html = $css->inline_html( $alias ); ``` This returns an embedded stylesheet referred to by `$alias`. ## link\_or\_inline\_html ```perl my $html = $css->link_or_inline_html( @aliases ); ``` This returns either the link HTML markup, or the embedded stylesheet, if the file size is not greater than ["inline\_max"](#inline_max). Note that a stylesheet will be inlined, even if there is are ["cdn\_links"](#cdn_links). ## deferred\_link\_html ```perl my $html = $css->deferred_link_html( @aliases ); ``` This returns the HTML markup for the stylesheets specified by ["aliases"](#aliases), as appropriate for each stylesheet. If the stylesheets are not greater than ["inline\_max"](#inline_max), then it will embed them. Otherwise it will return the appropriate markup, depending on ["defer\_css"](#defer_css). # KNOWN ISSUES ## XHTML Support This module is written for HTML5. It does not support XHTML self-closing elements or embedding styles and scripts in CDATA sections. ## Encoding All files are embedded as raw files. No URL encoding is done on the HTML links or ["asset\_id"](#asset_id). ## It's spelled "Deferrable" It's also spelled "Deferable". # SOURCE The development version is on github at [https://github.com/robrwo/HTML-DeferableCSS](https://github.com/robrwo/HTML-DeferableCSS) and may be cloned from [git://github.com/robrwo/HTML-DeferableCSS.git](git://github.com/robrwo/HTML-DeferableCSS.git) # BUGS Please report any bugs or feature requests on the bugtracker website [https://github.com/robrwo/HTML-DeferableCSS/issues](https://github.com/robrwo/HTML-DeferableCSS/issues) When submitting a bug or request, please include a test-file or a patch to an existing test-file that illustrates the bug or desired feature. Please report any bugs in `cssrelpreload.js` to [https://github.com/filamentgroup/loadCSS/issues](https://github.com/filamentgroup/loadCSS/issues). # AUTHOR Robert Rothenberg This module was developed from work for Science Photo Library [https://www.sciencephoto.com](https://www.sciencephoto.com). `reset.css` comes from [http://meyerweb.com/eric/tools/css/reset/](http://meyerweb.com/eric/tools/css/reset/). `cssrelpreload.js` comes from [https://github.com/filamentgroup/loadCSS/](https://github.com/filamentgroup/loadCSS/). # COPYRIGHT AND LICENSE This software is Copyright (c) 2020 by Robert Rothenberg. This is free software, licensed under: ``` The MIT (X11) License ```