feat: lazy-load non-critical vendor CSS - #965
Conversation
|
This pull request contains changes to the configuration file. Please make sure the documentation in NexT website is changed or added. |
|
@pivaldi Thanks for splitting this change into a separate PR. One concern is that this reintroduces an inline event handler:
NexT previously removed this pattern specifically to support CSP without
Could we keep the lazy-loading logic in an external script instead? The smallest change would be to mark these links with a data attribute and let some deferred js code change their
This avoids introducing another script request, preserves the no-JavaScript fallback, and does not require |
|
Separately, for users mainly concerned about the Font Awesome loading speed, I created next-theme/hexo-next-fontawesome-subset. It scans the final Hexo routes and generates site-specific subset WOFF2 files containing only the Font Awesome glyphs actually used by the site, while preserving the existing fa-* class API and the official all.min.css. |
|
Thanks for working on this and for splitting the CSS delivery change into a focused PR. During review, I realized that the NexT organization already maintains this functionality in filter_optimize:
css:
delivery:
- font-awesome
- fontawesome-free
- fancybox
- katexWe think CSS delivery is better handled as a generic build optimization rather than as theme-specific template behavior. Keeping it in
Selective control is also useful because Font Awesome and KaTeX may be required above the fold on some sites, where delaying them could cause FOUC or layout shifts. This review also exposed an issue in the current For these reasons, we do not plan to merge this PR. This is not a reflection on the effort or quality of the contribution. It helped us identify both the overlap and an improvement needed in our existing optimizer. Thank you again for the proposal and the careful explanation of the performance motivation. |
Motivation
FontAwesome, Fancybox and KaTeX CSS are render-blocking but not needed for
first paint. Loading them eagerly hurts Lighthouse / Core Web Vitals (FCP, LCP)
on pages that don't use them above the fold. This makes those stylesheets
non-render-blocking via opt-in lazy loading.
Changes
New opt-in config (
_config.yml), disabled by default so behavior isunchanged unless enabled:
next_vendorshelper (scripts/helpers/engine.js) accepts an optionsobject with a
lazyflag. Whenlazyis set andperformance.lazy_cssis enabled, the stylesheet is loaded with the standard preload +
onloadswap technique, plus a
<noscript>fallback for JS-disabled clients:JS handling is unchanged (it already uses
defer). Existingintegrity/crossoriginattributes are preserved in both the preload and noscript tags.Templates opt the three non-critical stylesheets in:
layout/_partials/head/head.njk—fontawesome,fancybox_csslayout/_third-party/math/katex.njk—katexNotes
performance.lazy_css: true.next_vendors(name)still works; the options argumentis optional.
Testing
performance.lazy_css: false(default): tags render exactly as before(render-blocking
<link rel="stylesheet">).performance.lazy_css: true: FontAwesome / Fancybox / KaTeX CSS emit thepreload+onloadswap with a<noscript>fallback; styles still applywith and without JavaScript.