diff --git a/README.md b/README.md index f950e15..7a8228e 100644 --- a/README.md +++ b/README.md @@ -14,13 +14,16 @@ Once installed, the module will set the Requirements system to use the enhanced ## Usage -The module extends the standard `Requirements` methods, providing additional options. Currently, these additional options are available: +The module extends the standard `Requirements` methods, providing additional options. Currently, these additional options are available for both CSS and JS files: - inline - preload - push - nonce +The following option is also available for CSS files: + +- defer ### inline @@ -65,6 +68,17 @@ Link ; rel=preload; as=style This adds the HTML 'nonce' attribute as required. Can be useful for dealing with CSP implementations +### defer (css) + +If the defer option is added to a CSS inclusion, a tag will be injected into the head of the document which loads the specified CSS file after the page has loaded. This can help to reduce page blocking for styles which are not needed for the initial rendering. +In order to provide support for browsers which do not run javascript, a noscript tag is also added. +The resultant output looks like this: + +``` + + +``` + ## Tag ordering diff --git a/src/View/Enhanced_Backend.php b/src/View/Enhanced_Backend.php index 7d269e4..5af8e7d 100644 --- a/src/View/Enhanced_Backend.php +++ b/src/View/Enhanced_Backend.php @@ -2,7 +2,6 @@ namespace DorsetDigital\EnhancedRequirements\View; -use Exception; use InvalidArgumentException; use SilverStripe\Control\Controller; use SilverStripe\Control\Director; @@ -262,14 +261,19 @@ private function inlineCSS($file): void * - 'preload' : (boolean) Add preload headers * - 'inline' : (boolean) Include this asset inline instead of loading * - 'push' : (boolean) add http headers to initiate http/2 push + * - 'defer' : (boolean) insert the CSS into the page using deferred loading */ public function css($file, $media = null, $options = []) { $file = ModuleResourceLoader::singleton()->resolvePath($file); $inline = $options['inline'] ?? null; + $defer = $options['defer'] ?? null; + if ($file && ($inline === true)) { $this->inlineCSS($file); + } else if ($file && ($defer === true)) { + $this->addDeferredCSS($file); } else { $integrity = $options['integrity'] ?? null; $crossorigin = $options['crossorigin'] ?? null; @@ -304,6 +308,29 @@ public function css($file, $media = null, $options = []) } } + /** + * Adds CSS tags for deferred loading of a CSS file + * @param $file + * @return void + */ + private function addDeferredCSS($file) + { + $tag = HTML::createTag('link', [ + 'rel' => 'preload', + 'href' => $this->pathForFile($file), + 'as' => 'style', + 'onload' => "this.onload=null;this.rel='stylesheet'" + ], ''); + $nsTag = HTML::createTag('noscript', [], + HTML::createTag('link', [ + 'rel' => 'stylesheet', + 'href' => $this->pathForFile($file) + ]) + ); + self::insertHeadTags($tag); + self::insertHeadTags($nsTag); + } + /** * Adds a script to the page inline * @param $file