Nodejs tool which helps to build/inject critical/component CSS for AEM templates/components (Adobe Experience Manager).
It can be used as components CSS dependency resolver/injector (not as automatically code splitter/extractor).
- Install
- How to use
- Regular Workflow
- API
- Config
- Injection type - Inline
- Injection type - Link
- Best practice
- FAQ
- Links
- Fast, flexible, powerful
- Configurable
- Inline injection via
style
tag - Standalone injection via
link
tag - Single injection (on the page)
- Auto-resolving injection type by file size
- Hashes for files injected via
link
tag - Supports
.css
,.scss
,.sass
,.less
files - Partial injection (css depends on component configuration)
- Tested on several AEM projects
- etc.
- Install NodeJs (This will also install npm)
- Install @dmantsevich/aem-critical-css as dependency for your project (👍):
npm i @dmantsevich/aem-critical-css --save
That section shows basic usage for beginners.
- Open AEM component template and add next code (where "path/to/component-css.less" is path to critical css file, which should be injected. Path is related to
${config.css.sourceRoot}
(see config). Supports: less, scss, sass, css types):
<sly data-sly-use.aemCriticalCSS="${'./_aem-critical-css.js'}"
@aem-critical-css="path/to/component-css.less">${aemCriticalCSS.inject @ context="unsafe"}</sly>
- Go to folder where frontend team are working (
cd ui.frontend
orcd ui.clientlibs
or other) - Install AEM Critical CSS module/package as dependency (see Install section):
npm i @dmantsevich/aem-critical-css --save
- Create
aem-critical-css.js
file (in the future webpack, gulp & grunt wrappers will be added) with code:
const { process } = require('@dmantsevich/aem-critical-css');
const config = {}; // it is configuration for the project
process(config);
- Process templates (see Regular Workflow section) (it should be a part of frontend build):
node aem-critical-css.js
- If processing was successful, then you can find generated css file (aem-critical-css.js) near AEM component template.
- You can deploy code to AEM
- Tool is searching all
"*.html"
files (HTL) under${config.AEM.components}
(by default: ui.apps/src/main/content/jcr_root/apps/ folder | see config) folder - Analyzing all found files, which contains
${criticalCSS.file}.${criticalCSS.type}
(by default: _aem-critical-css.js string | see config) string. - Parsing
${config.criticalCSS.sourceAttr}
,${config.criticalCSS.injectionTypeAttr}
,${config.criticalCSS.serviceAttr}
attributes. (by default: @aem-critical-css, @aem-critical-css-injectiontype, @aem-critical-css-service attributes | see config) - If parsing was successful, then starts generating CSS code linked in
${config.criticalCSS.sourceAttr}
(by default: @aem-critical-css attribute | see config) attribute.- Reading source
${config.css.sourceRoot}/${@aem-critical-css-attribute-value}
file (by default: ./${aem-critical-css-attribute-value} | see config) - Compile source file with less, node-sass compiler (you can create your custom compiler)
- Process CSS with postcss plugins (by default: autoprefixer, cssnano | see config)
- Reading source
- Resolve injection type
- If ${config.criticalCSS.injectionTypeAttr} attribute (by default: @aem-critical-css-injectiontype | see config) is defined, then it will be used
- Otherwise ${config.criticalCSS.injectionType} value (by default: auto | see config) will be used
- Resolving for injection type auto:
- Calculating filesize for generated CSS file (after gzip)
- If filesize is lower
${config.criticalCSS.gzipSize}
(by default: 10kb | see config) then file will be injected via<style>
tag. - Otherwise file will be injected via
<link>
tag.
- If injection type is link, then css file(file name will contains hash) will be saved under ${config.web.localClientlib}/resources/ folder (by default: ui.apps/src/main/content/jcr_root/apps/aem-critical-css/resources/ | see config)
- Generating
${criticalCSS.file}.${criticalCSS.type}
(by default: _aem-critical-css.js | see config) file in the same folder with HTL template (where it used).
Next properties & method exports @dmantsevich/aem-critical-css module:
- process(config) {function} - process AEM templates & generate css files for injection.
- CRITICAL_CSS_TYPES {constants} - contains possible types for critical css files. Uses in configuration
${config.criticalCSS.type}
. See config section - INJECTION_TYPES {constants} - contains possible values for configuration
${config.criticalCSS.injectionType}
. Also that values can be used in "@aem-critical-css-inectiontype" attribute.- INJECTION_TYPES.INLINE - inject css with
<style>
tag. (see Injection type - Inline) - INJECTION_TYPES.LINK - inject css with
<link href="....">
tag. (see Injection type - Link) - INJECTION_TYPES.AUTO - resolve injection type automatically. By default, if filesize(after gzip) is lower 10kb, then INLINE type will be used, otherwise LINK. See config section
- INJECTION_TYPES.INLINE - inject css with
Default config file here: /main/lib/config.js
Property | Description |
---|---|
AEM.projectRoot |
{String} Path to AEM Project root folder. Default value: ./../ (parent folder) |
AEM.components |
{String} Path to HTL templates which should be processed. Path should be relative to ${config.AEM.projectRoot} . Default value: ui.apps/src/main/content/jcr_root/apps/ |
criticalCSS.file |
{String} Name for output(generated) files. Result filename: ${config.criticalCSS.file}.${config.criticalCSS.type} . See Regular Workflow section. Default value: _aem-critical-css |
criticalCSS.type |
{CRITICAL_CSS_TYPES.USEAPI / CRITICAL_CSS_TYPES.TEMPLATE} Output file type. Default value: CRITICAL_CSS_TYPES.USEAPI |
criticalCSS.injectionType |
{INJECTION_TYPES.AUTO / INJECTION_TYPES.INLINE / INJECTION_TYPES.LINK} Default injection type (if @aem-critical-css-injectiontype attribute isn't defined). Default value: INJECTION_TYPES.AUTO |
criticalCSS.injectionTypeAutoResolver |
{Function(criticalCSSDefObj)} Function-Resolver for INJECTION_TYPES.AUTO . Calling for each AEM Critical CSS definition. Should return INJECTION_TYPES.INLINE or INJECTION_TYPES.LINK . By default: based on CSS GZip size(getGzip(css) < config.criticalCSS.gzipSize ? INJECTION_TYPES.INLINE : INJECTION_TYPES.LINK ). See criticalCSS.gzipSize option. |
criticalCSS.gzipSize |
{Integer} Default value: 10kb. If CSS GZip size lower than is value, then css will be injected - INJECTION_TYPES.INLINE . Otherwise: INJECTION_TYPES.LINK . Working only with default criticalCSS.injectionTypeAutoResolver |
criticalCSS.sourceAttr |
{String} Attribute with path to css source file. Default value: @aem-critical-css |
criticalCSS.injectionTypeAttr |
{String} Attribute with injection type configuration. If attribute isn't present, then criticalCSS.injectionType value will be used. Default value: @aem-critical-css-injectiontype |
criticalCSS.serviceAttr |
{String} Attribute with path (should be relative to jcr_root) to custom injector service. Default value: @aem-critical-css-service . Level: Expert. |
criticalCSS.useAPIService |
{String} Path (should be relative to jcr_root) to default JS/Java css injector service. By default: built-in service (AEMCriticalCSSService.js). Level: Expert. |
criticalCSS.AEMCriticalCSSServiceDestination |
{String} Path, where build-in (AEMCriticalCSSService.js) file will be saved. Default value: ui.apps/src/main/content/jcr_root/apps/aem-critical-css/utils/ . Level: Expert. |
criticalCSS.minifyOutput |
{Boolean} Minify output(for generated _aem-critical-css.html, _aem-critical-css.js files). Default value: true |
For small or important(critical) css files, that type is more - preferable. Because request to small files can be bigger (+ non-blocking rendition), than css content.
HTML output for component/critical css file will be (just example):
<!-- @aem-critical-css: path/to/component-css.less -->
<style>/*2021-2-21 0:49:06*/.my-component{border:1px solid red}.my-component a{border:1px solid green}</style>
That type is better for rarely used components on site pages. That files can be cached in user browser.
HTML output for component/critical css file will be (just example):
<!-- @aem-critical-css: path/to/component-css.less -->
<link href="/etc.clientlibs/aem-critical-css/resources/path/to/component-css.1ha51609gjk2.css" rel="stylesheet"/>
Should helps to split & inject only necessary CSS for your component (depends on component configuration)
TBD
Will describe how to create own service
TBD
- Add _aem-critical-css.js, _aem-critical-css.html files (see config) to your .gitignore file
- Add ui.apps/src/main/content/jcr_root/apps/aem-critical-css/ folder (see config) to your .gitignore file
TBD
If you have any questions or you need help, feel free to ask via github: Issues
Most popular questions/answers will be here
TBD
TBD
🧰
2021