在AnQiCMS中,优化网站加载速度是提升用户体验和搜索引擎排名的关键一步。当文章内容中包含大量图片时,这些图片会显著增加页面加载时间。图片懒加载(Lazy Loading)正是一种高效解决此问题的方法,它能让图片在进入用户视野之前不加载,从而加快页面初始渲染速度。

AnQiCMS作为一个注重性能和SEO的内容管理系统,提供了对文章内容中图片实现懒加载的灵活支持。您可以通过简单的模板配置,结合前端JavaScript,轻松为您的网站启用这一功能。

了解图片懒加载的原理

图片懒加载的核心思想是延迟加载非视口(viewport)内的图片资源。通常,浏览器在解析HTML时会立即下载所有<img>标签的src属性指定的图片。而懒加载技术通过将图片的实际地址存储在data-srcdata-original等自定义属性中,而src属性则指向一个轻量的占位符图片(甚至为空)。当用户滚动页面,图片即将进入可视区域时,前端的JavaScript代码会捕获到这一事件,然后将data-src中的真实图片地址赋值给src,图片才开始下载和显示。

AnQiCMS如何支持文章内容图片懒加载

AnQiCMS在处理文章详情页内容时,提供了内置的机制来协助实现图片懒加载。这主要体现在archiveDetail标签对Content字段的渲染上。

在文章详情页模板中,我们通常会使用archiveDetail标签来输出文章的正文内容。例如:

<div>文档内容:{% archiveDetail archiveContent with name="Content" %}{{archiveContent|safe}}</div>

为了启用懒加载,AnQiCMS允许您在archiveDetail标签中为Content字段添加一个lazy参数。这个参数的作用是告诉AnQiCMS,在渲染文章内容中的<img>标签时,将其src属性的内容替换到您指定的自定义属性中,并将src属性清空或设置为占位符。

假设您希望使用data-src作为图片真实地址的存储属性,那么您可以这样修改您的模板代码:

<div>文档内容:{% archiveDetail archiveContent with name="Content" lazy="data-src" %}{{archiveContent|safe}}</div>

在这里,lazy="data-src"表示AnQiCMS在生成HTML时,会将所有<img>标签的src内容移动到data-src属性,同时src属性可能被清空。|safe过滤器在这里是必要的,它指示AnQiCMS将输出的HTML内容视为安全内容,不进行转义,以确保图片标签能正确渲染。

完成这一步后,文章内容中的图片在页面加载时将不再直接通过src加载,而是等待前端JavaScript的介入。

前端JavaScript实现懒加载的步骤

仅仅修改AnQiCMS的模板标签并不能直接实现图片懒加载,您还需要引入一段JavaScript代码来检测图片是否进入可视区域并触发加载。这通常涉及到以下几个步骤:

  1. 选择一个合适的懒加载库或原生支持: 现代浏览器已经原生支持loading="lazy"属性,这是最简单且性能**的方案。您可以在<img>标签中直接添加loading="lazy"。当使用AnQiCMS的lazy="data-src"时,如果您的JS懒加载库能将data-src转为src,而src也同时含有loading="lazy",那么就能很好地结合使用。 如果需要兼容旧浏览器,您可以选择一些轻量级的前端懒加载库,例如vanilla-lazyloadLozad.jsIntersection Observer API的polyfill方案。这些库通常会监听滚动事件或使用Intersection Observer API来检测元素可见性。

  2. 引入JavaScript代码到您的模板: 您需要将选择的懒加载JavaScript库文件或自定义的JavaScript代码引入到您的网站模板中。根据AnQiCMS的模板约定,静态资源文件通常存放在/public/static/目录下。您可以在网站的公共头部模板(如partial/header.html)或底部模板(如partial/footer.html,通常在</body>标签之前)引入。

    例如,如果您使用原生loading="lazy",且您的JS逻辑只是将data-src转为src,您可以这样引入一个简单的自定义JS:

    <!-- 引入自定义懒加载JS文件 -->
    <script src="{% system with name="TemplateUrl" %}/js/lazyload.js"></script>
    

    或者,直接在HTML中编写初始化代码(不推荐用于复杂逻辑):

    <script>
    document.addEventListener("DOMContentLoaded", function() {
        var lazyImages = [].slice.call(document.querySelectorAll("img[data-src]"));
    
    
        if ("IntersectionObserver" in window) {
            let lazyImageObserver = new IntersectionObserver(function(entries, observer) {
                entries.forEach(function(entry) {
                    if (entry.isIntersecting) {
                        let lazyImage = entry.target;
                        lazyImage.src = lazyImage.dataset.src;
                        lazyImage.removeAttribute("data-src"); // 移除data-src属性
                        lazyImage.setAttribute("loading", "lazy"); // 添加原生懒加载属性
                        lazyImageObserver.unobserve(lazyImage);
                    }
                });
            });
    
    
            lazyImages.forEach(function(lazyImage) {
                lazyImageObserver.observe(lazyImage);
            });
        } else {
            // Fallback for older browsers without Intersection Observer
            // (e.g., attach to scroll, resize, orientationchange events)
            // This part can be more complex or use a dedicated library.
            let lazyLoadThrottleTimeout;
            function lazyload () {
                if (lazyLoadThrottleTimeout) {
                    clearTimeout(lazyLoadThrottleTimeout);
                }
                lazyLoadThrottleTimeout = setTimeout(function() {
                    let scrollTop = window.pageYOffset;
                    lazyImages.forEach(function (img) {
                        if (img.offsetTop < (window.innerHeight + scrollTop)) {
                            img.src = img.dataset.src;
                            img.removeAttribute("data-src");
                            img.setAttribute("loading", "lazy");
                        }
                    });
                    lazyImages = lazyImages.filter(function (img) {
                        return img.hasAttribute('data-src');
                    });
                    if (lazyImages.length == 0) {
                        document.removeEventListener("scroll", lazyload);
                        window.removeEventListener("resize", lazyload);
                        window.removeEventListener("orientationChange", lazyload);
                    }
                }, 20);
            }
    
    
            document.addEventListener("scroll", lazyload);
            window.addEventListener("resize", lazyload);
            window.addEventListener("orientationChange", lazyload);
        }
    });
    </script>
    

    请注意,上述JavaScript代码是一个简单的示例,用于说明懒加载的逻辑。在实际应用中,您可能需要根据所选懒加载库的官方文档进行更详细的配置和初始化。

具体操作流程总结

  1. 发布或编辑文章: 在AnQiCMS后台发布或编辑文章时,正常插入图片即可,无需特殊操作。系统会将这些图片以标准的<img>标签形式存储。
  2. 修改文章详情页模板: 找到您的文章详情页模板(通常位于/template/您的模板目录/{模型table}/detail.html),将输出文章内容的archiveDetail标签修改为包含lazy="data-src"参数的形式:
    
    <div class="article-content">
        {% archiveDetail articleContent with name="Content" lazy="data-src" %}{{articleContent|safe}}
    </div>
    
  3. 引入并初始化懒加载JavaScript: 在您的网站公共模板文件(例如base.html,通常在<head></body>标签之前)中,引入您选择的懒加载JavaScript库,并根据该库的文档进行初始化。如果使用上述原生Intersection Observer的示例,可以直接粘贴代码。

优化和注意事项

  • 首屏图片避免懒加载: 对于页面首次加载时就出现在用户视野中的图片(Above the Fold),不建议对其进行懒加载