文章目录
-
- 在当今互联网环境中,网站加载速度已成为影响用户体验、搜索引擎排名和转化率的关键因素。据统计,页面加载时间每增加1秒,转化率就会下降7%。对于WordPress网站而言,图片通常是页面中最大的资源,占用了大量的带宽和加载时间。 图片懒加载和CDN加速是解决这一问题的两个关键技术: 图片懒加载:延迟加载非视口内的图片,只有当用户滚动到图片附近时才加载,显著减少初始页面加载时间。 CDN加速:通过全球分布的服务器网络分发静态资源,减少用户与服务器之间的物理距离,加快资源加载速度。 本文将手把手教您如何通过WordPress代码二次开发,集成智能化的图片懒加载与CDN加速功能,无需依赖臃肿的插件,实现轻量高效的性能优化。
-
- WordPress通过the_content()函数和特色图像功能输出图片时,会生成标准的HTML <img>标签。例如: <img src="https://example.com/wp-content/uploads/2023/05/image.jpg" alt="示例图片" width="800" height="600" class="aligncenter size-full wp-image-123"> 这种传统方式会在页面加载时立即请求所有图片,无论用户是否能看到它们。
- 现代网站优化通常采用以下技术: 响应式图片:根据设备屏幕尺寸提供不同大小的图片 下一代图片格式:WebP、AVIF等更高效的格式 懒加载:延迟加载非视口图片 CDN分发:通过边缘节点快速交付图片
-
- 懒加载的核心思想是:将图片的src属性替换为data-src属性,当图片进入视口时,再将data-src的值赋给src属性,触发图片加载。
- 在您的WordPress主题的functions.php文件中添加以下代码: /** * 为WordPress图片添加懒加载功能 */ function add_lazy_loading_to_images($content) { // 如果内容为空,直接返回 if (empty($content)) { return $content; } // 创建DOM文档对象 $dom = new DOMDocument(); // 抑制HTML解析错误警告 libxml_use_internal_errors(true); // 加载HTML内容,指定编码为UTF-8 $dom->loadHTML('<?xml encoding="UTF-8">' . $content); // 清除错误 libxml_clear_errors(); // 获取所有图片标签 $images = $dom->getElementsByTagName('img'); // 遍历所有图片 foreach ($images as $image) { // 获取原始src $src = $image->getAttribute('src'); // 如果src为空,跳过 if (empty($src)) { continue; } // 获取图片类名 $classes = $image->getAttribute('class'); // 排除某些不需要懒加载的图片(如首屏图片) if (strpos($classes, 'no-lazy') !== false) { continue; } // 将src转换为data-src $image->setAttribute('data-src', $src); // 设置占位符(1x1像素的透明GIF) $image->setAttribute('src', 'data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=='); // 添加懒加载类 $new_classes = $classes . ' lazy-load'; $image->setAttribute('class', trim($new_classes)); // 添加noscript标签作为降级方案 $noscript = $dom->createElement('noscript'); $noscript_img = $dom->createElement('img'); $noscript_img->setAttribute('src', $src); // 复制所有原始属性到noscript图片 foreach ($image->attributes as $attr) { if ($attr->nodeName !== 'data-src' && $attr->nodeName !== 'class') { $noscript_img->setAttribute($attr->nodeName, $attr->nodeValue); } } $noscript->appendChild($noscript_img); $image->parentNode->insertBefore($noscript, $image->nextSibling); } // 保存修改后的HTML $content = $dom->saveHTML(); // 提取body内容 $content = preg_replace('/^<!DOCTYPE.+?>/', '', $content); $content = str_replace(array('<html>', '</html>', '<body>', '</body>'), array('', '', '', ''), $content); return $content; } // 将懒加载应用到文章内容 add_filter('the_content', 'add_lazy_loading_to_images', 99); // 将懒加载应用到文章摘要 add_filter('get_the_excerpt', 'add_lazy_loading_to_images', 99); // 将懒加载应用到小工具内容 add_filter('widget_text', 'add_lazy_loading_to_images', 99);
- 在主题的footer.php文件之前或使用wp_footer钩子添加JavaScript代码: /** * 添加懒加载JavaScript */ function add_lazy_load_script() { ?> <script> (function() { 'use strict'; // 懒加载配置 var lazyLoadConfig = { // 图片进入视口前多少像素开始加载 rootMargin: '50px 0px', // 图片加载阈值 threshold: 0.01 }; // 检查浏览器是否支持IntersectionObserver if ('IntersectionObserver' in window) { // 使用IntersectionObserver API实现懒加载 var lazyImages = document.querySelectorAll('img.lazy-load'); var imageObserver = new IntersectionObserver(function(entries, observer) { entries.forEach(function(entry) { if (entry.isIntersecting) { var lazyImage = entry.target; // 替换data-src为src if (lazyImage.dataset.src) { lazyImage.src = lazyImage.dataset.src; } // 替换data-srcset为srcset(响应式图片) if (lazyImage.dataset.srcset) { lazyImage.srcset = lazyImage.dataset.srcset; } // 加载完成后移除懒加载类 lazyImage.onload = function() { lazyImage.classList.remove('lazy-load'); lazyImage.classList.add('lazy-loaded'); }; // 处理加载错误 lazyImage.onerror = function() { lazyImage.classList.remove('lazy-load'); lazyImage.classList.add('lazy-error'); console.error('图片加载失败: ' + lazyImage.dataset.src); }; // 停止观察该图片 imageObserver.unobserve(lazyImage); } }); }, lazyLoadConfig); // 开始观察所有懒加载图片 lazyImages.forEach(function(lazyImage) { imageObserver.observe(lazyImage); }); } else { // 不支持IntersectionObserver的降级方案 var lazyImages = document.querySelectorAll('img.lazy-load'); var lazyLoadThrottleTimeout; function lazyLoad() { if (lazyLoadThrottleTimeout) { clearTimeout(lazyLoadThrottleTimeout); } lazyLoadThrottleTimeout = setTimeout(function() { var scrollTop = window.pageYOffset; lazyImages.forEach(function(lazyImage) { if (lazyImage.offsetTop < (window.innerHeight + scrollTop)) { // 替换data-src为src if (lazyImage.dataset.src) { lazyImage.src = lazyImage.dataset.src; } // 替换data-srcset为srcset if (lazyImage.dataset.srcset) { lazyImage.srcset = lazyImage.dataset.srcset; } // 加载完成后移除懒加载类 lazyImage.onload = function() { lazyImage.classList.remove('lazy-load'); lazyImage.classList.add('lazy-loaded'); }; // 从数组中移除已处理的图片 lazyImages = Array.prototype.filter.call(lazyImages, function(image) { return image !== lazyImage; }); // 如果所有图片都已加载,移除滚动事件监听 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); // 初始加载 lazyLoad(); } // 添加CSS样式 var style = document.createElement('style'); style.textContent = ` img.lazy-load { opacity: 0; transition: opacity 0.3s; } img.lazy-loaded { opacity: 1; } img.lazy-error { opacity: 0.5; filter: grayscale(100%); } `; document.head.appendChild(style); })(); </script> <?php } add_action('wp_footer', 'add_lazy_load_script', 99);
-
- CDN(内容分发网络)通过将静态资源(如图片、CSS、JavaScript)缓存到全球分布的边缘服务器上,使用户可以从地理位置上最近的服务器获取资源,从而显著减少延迟。
- 在functions.php中添加以下代码,将本地资源URL替换为CDN URL: /** * 配置WordPress使用CDN */ function setup_cdn_for_wordpress() { // CDN配置 $cdn_config = array( // 启用CDN 'enabled' => true, // CDN域名(请替换为您的CDN域名) 'cdn_domain' => 'cdn.yourdomain.com', // 本地域名(您的WordPress网站域名) 'local_domain' => $_SERVER['HTTP_HOST'], // 要使用CDN的资源类型 'file_extensions' => array('jpg', 'jpeg', 'png', 'gif', 'webp', 'ico', 'svg', 'css', 'js', 'pdf', 'zip', 'mp4', 'mp3', 'woff', 'woff2', 'ttf', 'eot'), // 排除的路径(某些路径下的资源不使用CDN) 'exclude_paths' => array('/wp-admin/', '/wp-includes/', '/wp-content/plugins/', '/wp-content/themes/'), // 是否对管理员禁用CDN 'disable_for_admin' => true ); // 如果CDN未启用,直接返回 if (!$cdn_config['enabled']) { return; } // 对管理员禁用CDN if ($cdn_config['disable_for_admin'] && current_user_can('manage_options')) { return; } // 返回配置 return $cdn_config; } /** * 将本地URL替换为CDN URL */ function replace_urls_with_cdn($url) { // 获取CDN配置 $cdn_config = setup_cdn_for_wordpress(); // 如果没有配置或CDN未启用,返回原URL if (!$cdn_config || !$cdn_config['enabled']) { return $url; } // 解析URL $parsed_url = parse_url($url); // 如果不是HTTP/HTTPS协议,返回原URL if (!isset($parsed_url['scheme']) || !in_array($parsed_url['scheme'], array('http', 'https'))) { return $url; } // 检查主机名是否匹配本地域名 if (isset($parsed_url['host']) && $parsed_url['host'] === $cdn_config['local_domain']) { // 检查路径是否在排除列表中 if (isset($parsed_url['path'])) { foreach ($cdn_config['exclude_paths'] as $exclude_path) { if (strpos($parsed_url['path'], $exclude_path) === 0) { return $url; } } } // 检查文件扩展名 $path = isset($parsed_url['path']) ? $parsed_url['path'] : ''; $extension = pathinfo($path, PATHINFO_EXTENSION); if (empty($extension) || !in_array(strtolower($extension), $cdn_config['file_extensions'])) { return $url; } // 替换域名为CDN域名 $url = str_replace( $cdn_config['local_domain'], $cdn_config['cdn_domain'], $url ); } return $url; } // 应用CDN替换到各种URL add_filter('wp_get_attachment_url', 'replace_urls_with_cdn'); add_filter('the_content', 'cdn_replace_content_urls', 99); add_filter('widget_text', 'cdn_replace_content_urls', 99); add_filter('stylesheet_uri', 'replace_urls_with_cdn'); add_filter('script_loader_src', 'replace_urls_with_cdn'); add_filter('style_loader_src', 'replace_urls_with_cdn'); /** * 替换内容中的URL为CDN URL */ function cdn_replace_content_urls($content) { // 获取CDN配置 $cdn_config = setup_cdn_for_wordpress(); // 如果没有配置或CDN未启用,返回原内容 if (!$cdn_config || !$cdn_config['enabled']) { return $content; } // 正则表达式匹配URL $local_domain = preg_quote($cdn_config['local_domain'], '/'); $cdn_domain = $cdn_config['cdn_domain']; // 匹配图片、CSS、JS等资源的URL $pattern = '/https?://' . $local_domain . '/[^"'s]*.(' . implode('|', $cdn_config['file_extensions']) . ')(?:?[^"'s]*)?/i'; // 替换URL $content = preg_replace_callback($pattern, function($matches) use ($cdn_config) { $url = $matches[0]; // 检查路径是否在排除列表中 foreach ($cdn_config['exclude_paths'] as $exclude_path) { if (strpos($url, $exclude_path) !== false) { return $url; } } // 替换域名为CDN域名 return str_replace( '//' . $cdn_config['local_domain'], '//' . $cdn_config['cdn_domain'], $url ); }, $content); return $content; }
- 现代CDN通常支持自动图片格式转换。以下代码可以检测浏览器是否支持WebP,并相应调整图片URL: /** * 根据浏览器支持自动提供WebP格式图片 */ function provide_webp_when_supported($url, $attachment_id) { // 获取CDN配置 $cdn_config = setup_cdn_for_wordpress(); // 如果没有配置或CDN未启用,返回原URL if (!$cdn_config || !$cdn_config['enabled']) { return $url; } // 检查URL是否已经是CDN URL if (strpos($url, $cdn_config['cdn_domain']) === false) { return $url; } // 检查文件扩展名 $extension = pathinfo($url, PATHINFO_EXTENSION); $supported_extensions = array('jpg', 'jpeg', 'png'); if (!in_array(strtolower($extension), $supported_extensions)) { return $url; } // 检查浏览器是否支持WebP if (isset($_SERVER['HTTP_ACCEPT']) && strpos($_SERVER['HTTP_ACCEPT'], 'image/webp') !== false) { // 在URL中添加WebP参数或修改扩展名 // 这取决于您的CDN提供商如何配置WebP转换 // 示例:在URL末尾添加?format=webp if (strpos($url, '?') === false) { $url .= '?format=webp'; } else { $url .= '&format=webp'; } } return $url; } // 为图片URL添加WebP支持检测 add_filter('wp_get_attachment_url', 'provide_webp_when_supported', 10, 2); add_filter('the_content', 'add_webp_support_to_content', 99); /** * 为内容中的图片添加WebP支持 */ function add_webp_support_to_content($content) { // 如果浏览器不支持WebP,直接返回 if (!isset($_SERVER['HTTP_ACCEPT']) || strpos($_SERVER['HTTP_ACCEPT'], 'image/webp') === false) { return $content; } // 获取CDN配置 $cdn_config = setup_cdn_for_wordpress(); // 如果没有配置或CDN未启用,返回原内容 if (!$cdn_config || !$cdn_config['enabled']) { return $content; } 图片URL并添加WebP参数 $cdn_domain = preg_quote($cdn_config['cdn_domain'], '/'); $pattern = '/https?://' . $cdn_domain . '/[^"'s]*.(jpg|jpeg|png)(?:?[^"'s]*)?/i'; $content = preg_replace_callback($pattern, function($matches) { $url = $matches[0]; // 添加WebP格式参数 if (strpos($url, '?') === false) { return $url . '?format=webp'; } else { return $url . '&format=webp'; } }, $content); return $content; } ## 第四部分:集成响应式图片支持 ### 4.1 WordPress响应式图片基础 WordPress 4.4+ 已内置响应式图片支持,但我们可以进一步优化: /** 增强WordPress响应式图片功能 */ function enhance_responsive_images($html, $attachment_id, $size, $icon, $attr) { // 获取原始图片URL $image_url = wp_get_attachment_url($attachment_id); if (!$image_url) { return $html; } // 获取图片元数据 $image_meta = wp_get_attachment_metadata($attachment_id); if (!$image_meta) { return $html; } // 获取CDN配置 $cdn_config = setup_cdn_for_wordpress(); // 如果是CDN URL,确保响应式图片srcset也使用CDN if ($cdn_config && $cdn_config['enabled']) { $html = str_replace( 'srcset="' . $cdn_config['local_domain'], 'srcset="' . $cdn_config['cdn_domain'], $html ); } // 添加懒加载属性 $html = preg_replace('/<img(.*?)src=/', '<img$1data-src=', $html); $html = preg_replace('/srcset=/', 'data-srcset=', $html); // 添加懒加载类 if (strpos($html, 'class="') !== false) { $html = preg_replace('/class="(.*?)"/', 'class="$1 lazy-load"', $html); } else { $html = preg_replace('/<img/', '<img class="lazy-load"', $html); } // 添加noscript回退 $noscript_html = preg_replace('/data-src=/', 'src=', $html); $noscript_html = preg_replace('/data-srcset=/', 'srcset=', $noscript_html); $noscript_html = preg_replace('/class="(.*?)lazy-load(.*?)"/', 'class="$1$2"', $noscript_html); $html .= '<noscript>' . $noscript_html . '</noscript>'; return $html; } // 应用增强的响应式图片功能add_filter('wp_get_attachment_image', 'enhance_responsive_images', 10, 5); ### 4.2 自定义图片尺寸生成 /** 添加自定义图片尺寸用于响应式设计 */ function add_custom_image_sizes() { // 添加各种设备适用的图片尺寸 add_image_size('retina_large', 1920, 0, false); // 大屏Retina设备 add_image_size('desktop_large', 1200, 0, false); // 桌面大屏 add_image_size('desktop_medium', 800, 0, false); // 桌面中屏 add_image_size('tablet_large', 600, 0, false); // 平板大屏 add_image_size('tablet_small', 400, 0, false); // 平板小屏 add_image_size('mobile_large', 300, 0, false); // 手机大屏 add_image_size('mobile_small', 150, 0, false); // 手机小屏 } add_action('after_setup_theme', 'add_custom_image_sizes'); /** 自定义图片尺寸的srcset */ function custom_image_srcset($sources, $size_array, $image_src, $image_meta, $attachment_id) { // 获取CDN配置 $cdn_config = setup_cdn_for_wordpress(); // 自定义尺寸映射 $custom_sizes = array( 'retina_large' => 1920, 'desktop_large' => 1200, 'desktop_medium' => 800, 'tablet_large' => 600, 'tablet_small' => 400, 'mobile_large' => 300, 'mobile_small' => 150 ); foreach ($custom_sizes as $size_name => $width) { // 检查是否有该尺寸的图片 if (isset($image_meta['sizes'][$size_name])) { $image_url = wp_get_attachment_image_url($attachment_id, $size_name); // 应用CDN if ($cdn_config && $cdn_config['enabled']) { $image_url = replace_urls_with_cdn($image_url); } $sources[$width] = array( 'url' => $image_url, 'descriptor' => 'w', 'value' => $width, ); } } // 按宽度排序 ksort($sources); return $sources; } add_filter('wp_calculate_image_srcset', 'custom_image_srcset', 10, 5); ## 第五部分:性能优化与缓存策略 ### 5.1 浏览器缓存优化 /** 添加浏览器缓存头 */ function add_cache_headers() { // 如果不是管理页面 if (!is_admin()) { // 设置静态资源缓存时间(1年) $cache_time = 31536000; // 60*60*24*365 // 获取当前请求的扩展名 $request_uri = $_SERVER['REQUEST_URI']; $extension = pathinfo($request_uri, PATHINFO_EXTENSION); // 静态资源扩展名列表 $static_extensions = array( 'jpg', 'jpeg', 'png', 'gif', 'webp', 'ico', 'svg', 'css', 'js', 'pdf', 'zip', 'mp4', 'mp3', 'woff', 'woff2', 'ttf', 'eot' ); if (in_array(strtolower($extension), $static_extensions)) { header("Cache-Control: public, max-age={$cache_time}, immutable"); header("Expires: " . gmdate('D, d M Y H:i:s', time() + $cache_time) . ' GMT'); // 添加ETag $etag = md5($request_uri . filemtime(ABSPATH . $request_uri)); header("ETag: {$etag}"); } } } add_action('send_headers', 'add_cache_headers'); ### 5.2 资源预加载与预连接 /** 添加资源提示(Resource Hints) */ function add_resource_hints() { // 获取CDN配置 $cdn_config = setup_cdn_for_wordpress(); if ($cdn_config && $cdn_config['enabled']) { // 预连接到CDN域名 echo '<link rel="preconnect" href="https://' . esc_attr($cdn_config['cdn_domain']) . '" crossorigin>'; // DNS预获取 echo '<link rel="dns-prefetch" href="//' . esc_attr($cdn_config['cdn_domain']) . '">'; } // 预加载关键资源 echo '<link rel="preload" href="' . get_template_directory_uri() . '/assets/css/critical.css" as="style">'; echo '<link rel="preload" href="' . get_template_directory_uri() . '/assets/js/lazyload.js" as="script">'; } add_action('wp_head', 'add_resource_hints', 1); ## 第六部分:监控与调试功能 ### 6.1 性能监控 /** 添加性能监控 */ class PerformanceMonitor { private $start_time; private $queries = array(); public function __construct() { $this->start_time = microtime(true); // 监控数据库查询 if (defined('SAVEQUERIES') && SAVEQUERIES) { add_filter('query', array($this, 'log_query')); } } public function log_query($query) { $this->queries[] = array( 'query' => $query, 'time' => microtime(true) ); return $query; } public function get_performance_data() { $end_time = microtime(true); $load_time = ($end_time - $this->start_time) * 1000; // 转换为毫秒 $data = array( 'load_time' => round($load_time, 2), 'memory_usage' => round(memory_get_peak_usage() / 1024 / 1024, 2), 'query_count' => count($this->queries), 'cdn_enabled' => false ); // 检查CDN状态 $cdn_config = setup_cdn_for_wordpress(); if ($cdn_config && $cdn_config['enabled']) { $data['cdn_enabled'] = true; $data['cdn_domain'] = $cdn_config['cdn_domain']; } return $data; } } // 初始化性能监控$performance_monitor = new PerformanceMonitor(); /** 在页脚显示性能数据(仅管理员可见) */ function display_performance_data() { global $performance_monitor; if (current_user_can('manage_options')) { $data = $performance_monitor->get_performance_data(); echo '<div style="position:fixed;bottom:10px;right:10px;background:rgba(0,0,0,0.8);color:#fff;padding:10px;font-size:12px;z-index:9999;border-radius:5px;">'; echo '<strong>性能数据:</strong><br>'; echo '加载时间: ' . $data['load_time'] . 'ms<br>'; echo '内存使用: ' . $data['memory_usage'] . 'MB<br>'; echo '数据库查询: ' . $data['query_count'] . '<br>'; echo 'CDN: ' . ($data['cdn_enabled'] ? '已启用 (' . $data['cdn_domain'] . ')' : '未启用'); echo '</div>'; } } add_action('wp_footer', 'display_performance_data'); ### 6.2 图片加载错误处理 /** 图片加载错误处理 */ function handle_image_errors() { ?> <script> document.addEventListener('DOMContentLoaded', function() { // 监听图片加载错误 document.addEventListener('error', function(e) { if (e.target.tagName === 'IMG') { var img = e.target; // 如果是懒加载图片 if (img.classList.contains('lazy-load')) { // 尝试加载原始src(非CDN版本) var originalSrc = img.dataset.src; if (originalSrc) { // 移除CDN域名,尝试加载原始图片 var localSrc = originalSrc.replace('cdn.yourdomain.com', 'yourdomain.com'); img.src = localSrc; // 标记为回退加载 img.dataset.fallback = 'true'; } } // 添加错误类 img.classList.add('image-error'); // 可选:显示占位图 if (!img.dataset.placeholderSet) { img.style.backgroundColor = '#f0f0f0'; img.style.minHeight = '100px'; img.dataset.placeholderSet = 'true'; } } }, true); // 使用捕获阶段 }); </script> <style> .image-error { opacity: 0.5; filter: grayscale(100%); } .image-error::after { content: '图片加载失败'; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); color: #999; font-size: 12px; } </style> <?php } add_action('wp_footer', 'handle_image_errors'); ## 第七部分:完整集成与配置 ### 7.1 创建配置页面 /** 创建懒加载和CDN配置页面 */ class LazyLoadCDN_Settings { public function __construct() { add_action('admin_menu', array($this, 'add_admin_menu')); add_action('admin_init', array($this, 'settings_init')); } public function add_admin_menu() { add_options_page( '懒加载与CDN设置', '图片优化', 'manage_options', 'lazyload-cdn-settings', array($this, 'settings_page') ); } public function settings_init() { register_setting('lazyload_cdn', 'lazyload_cdn_settings'); add_settings_section( 'lazyload_cdn_section', '懒加载与CDN配置', array($this, 'settings_section_callback'), 'lazyload_cdn' ); // CDN域名设置 add_settings_field( 'cdn_domain', 'CDN域名', array($this, 'cdn_domain_render'), 'lazyload_cdn', 'lazyload_cdn_section' ); // 懒加载启用设置 add_settings_field( 'lazyload_enabled', '启用懒加载', array($this, 'lazyload_enabled_render'), 'lazyload_cdn', 'lazyload_cdn_section' ); // WebP支持设置 add_settings_field( 'webp_support', '启用WebP支持', array($this, 'webp_support_render'), 'lazyload_cdn', 'lazyload_cdn_section' ); // 排除路径设置 add_settings_field( 'exclude_paths', '排除路径', array($this, 'exclude_paths_render'), 'lazyload_cdn', 'lazyload_cdn_section' ); } public function cdn_domain_render() { $options = get_option('lazyload_cdn_settings'); ?> <input type="text" name="lazyload_cdn_settings[cdn_domain]" value="<?php echo isset($options['cdn_domain']) ? esc_attr($options['cdn_domain']) : ''; ?>" placeholder="cdn.yourdomain.com"> <p class="description">请输入您的CDN域名,例如:cdn.yourdomain.com</p> <?php } public function lazyload_enabled_render() { $options = get_option('lazyload_cdn_settings'); ?> <input type="checkbox" name="lazyload_cdn_settings[lazyload_enabled]" value="1" <?php checked(isset($options['lazyload_enabled']) && $options['lazyload_enabled']); ?>> <label>启用图片懒加载功能</label> <?php } public function webp_support_render() { $options = get_option('lazyload_cdn_settings'); ?> <input type="checkbox" name="lazyload_cdn_settings[webp_support]" value="1" <?php checked(isset($options['webp_support']) && $options['webp_support']); ?>> <label>为支持WebP的浏览器自动提供WebP格式图片</label> <?php } public function exclude_paths_render() { $options = get_option('lazyload_cdn_settings'); $paths = isset($options['exclude_paths']) ? $options['exclude_paths'] : "/wp-admin/n/wp-includes/"; ?> <textarea name="lazyload_cdn_settings[exclude_paths]" rows="5" cols="50"><?php echo esc_textarea($paths); ?></textarea> <p class="description">每行一个路径,这些路径下的资源将不使用CDN</p> <?php } public function settings_section_callback() { echo '配置图片懒加载和CDN加速功能'; } public function settings_page() { ?> <div class="wrap"> <h1>懒加载与CDN设置</h1> <form action="options.php" method="post"> <?php settings_fields('lazyload_cdn'); do_settings_sections('lazyload_cdn'); submit_button(); ?> </form> <div class="card"> <h2>使用说明</h2> <ol> <li>配置CDN域名后,所有静态资源将通过CDN加速</li> <li>懒加载功能会延迟加载非视口内的图片</li> <li>WebP支持会自动为兼容浏览器提供更小的图片格式</li> <li>保存设置后,请清除缓存以查看效果</li> </ol> </div> </div> <?php } } // 初始化设置页面if (is_admin()) { new LazyLoadCDN_Settings(); } ### 7.2 更新配置获取函数 /** 更新CDN配置获取函数,
在当今互联网环境中,网站加载速度已成为影响用户体验、搜索引擎排名和转化率的关键因素。据统计,页面加载时间每增加1秒,转化率就会下降7%。对于WordPress网站而言,图片通常是页面中最大的资源,占用了大量的带宽和加载时间。
图片懒加载和CDN加速是解决这一问题的两个关键技术:
- 图片懒加载:延迟加载非视口内的图片,只有当用户滚动到图片附近时才加载,显著减少初始页面加载时间。
- CDN加速:通过全球分布的服务器网络分发静态资源,减少用户与服务器之间的物理距离,加快资源加载速度。
本文将手把手教您如何通过WordPress代码二次开发,集成智能化的图片懒加载与CDN加速功能,无需依赖臃肿的插件,实现轻量高效的性能优化。
WordPress通过the_content()函数和特色图像功能输出图片时,会生成标准的HTML <img>标签。例如:
<img src="https://example.com/wp-content/uploads/2023/05/image.jpg"
alt="示例图片"
width="800"
height="600"
class="aligncenter size-full wp-image-123">
这种传统方式会在页面加载时立即请求所有图片,无论用户是否能看到它们。
现代网站优化通常采用以下技术:
- 响应式图片:根据设备屏幕尺寸提供不同大小的图片
- 下一代图片格式:WebP、AVIF等更高效的格式
- 懒加载:延迟加载非视口图片
- CDN分发:通过边缘节点快速交付图片
懒加载的核心思想是:将图片的src属性替换为data-src属性,当图片进入视口时,再将data-src的值赋给src属性,触发图片加载。
在您的WordPress主题的functions.php文件中添加以下代码:
/**
* 为WordPress图片添加懒加载功能
*/
function add_lazy_loading_to_images($content) {
// 如果内容为空,直接返回
if (empty($content)) {
return $content;
}
// 创建DOM文档对象
$dom = new DOMDocument();
// 抑制HTML解析错误警告
libxml_use_internal_errors(true);
// 加载HTML内容,指定编码为UTF-8
$dom->loadHTML('<?xml encoding="UTF-8">' . $content);
// 清除错误
libxml_clear_errors();
// 获取所有图片标签
$images = $dom->getElementsByTagName('img');
// 遍历所有图片
foreach ($images as $image) {
// 获取原始src
$src = $image->getAttribute('src');
// 如果src为空,跳过
if (empty($src)) {
continue;
}
// 获取图片类名
$classes = $image->getAttribute('class');
// 排除某些不需要懒加载的图片(如首屏图片)
if (strpos($classes, 'no-lazy') !== false) {
continue;
}
// 将src转换为data-src
$image->setAttribute('data-src', $src);
// 设置占位符(1x1像素的透明GIF)
$image->setAttribute('src', 'data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==');
// 添加懒加载类
$new_classes = $classes . ' lazy-load';
$image->setAttribute('class', trim($new_classes));
// 添加noscript标签作为降级方案
$noscript = $dom->createElement('noscript');
$noscript_img = $dom->createElement('img');
$noscript_img->setAttribute('src', $src);
// 复制所有原始属性到noscript图片
foreach ($image->attributes as $attr) {
if ($attr->nodeName !== 'data-src' && $attr->nodeName !== 'class') {
$noscript_img->setAttribute($attr->nodeName, $attr->nodeValue);
}
}
$noscript->appendChild($noscript_img);
$image->parentNode->insertBefore($noscript, $image->nextSibling);
}
// 保存修改后的HTML
$content = $dom->saveHTML();
// 提取body内容
$content = preg_replace('/^<!DOCTYPE.+?>/', '', $content);
$content = str_replace(array('<html>', '</html>', '<body>', '</body>'), array('', '', '', ''), $content);
return $content;
}
// 将懒加载应用到文章内容
add_filter('the_content', 'add_lazy_loading_to_images', 99);
// 将懒加载应用到文章摘要
add_filter('get_the_excerpt', 'add_lazy_loading_to_images', 99);
// 将懒加载应用到小工具内容
add_filter('widget_text', 'add_lazy_loading_to_images', 99);
在主题的footer.php文件之前或使用wp_footer钩子添加JavaScript代码:
/**
* 添加懒加载JavaScript
*/
function add_lazy_load_script() {
?>
<script>
(function() {
'use strict';
// 懒加载配置
var lazyLoadConfig = {
// 图片进入视口前多少像素开始加载
rootMargin: '50px 0px',
// 图片加载阈值
threshold: 0.01
};
// 检查浏览器是否支持IntersectionObserver
if ('IntersectionObserver' in window) {
// 使用IntersectionObserver API实现懒加载
var lazyImages = document.querySelectorAll('img.lazy-load');
var imageObserver = new IntersectionObserver(function(entries, observer) {
entries.forEach(function(entry) {
if (entry.isIntersecting) {
var lazyImage = entry.target;
// 替换data-src为src
if (lazyImage.dataset.src) {
lazyImage.src = lazyImage.dataset.src;
}
// 替换data-srcset为srcset(响应式图片)
if (lazyImage.dataset.srcset) {
lazyImage.srcset = lazyImage.dataset.srcset;
}
// 加载完成后移除懒加载类
lazyImage.onload = function() {
lazyImage.classList.remove('lazy-load');
lazyImage.classList.add('lazy-loaded');
};
// 处理加载错误
lazyImage.onerror = function() {
lazyImage.classList.remove('lazy-load');
lazyImage.classList.add('lazy-error');
console.error('图片加载失败: ' + lazyImage.dataset.src);
};
// 停止观察该图片
imageObserver.unobserve(lazyImage);
}
});
}, lazyLoadConfig);
// 开始观察所有懒加载图片
lazyImages.forEach(function(lazyImage) {
imageObserver.observe(lazyImage);
});
} else {
// 不支持IntersectionObserver的降级方案
var lazyImages = document.querySelectorAll('img.lazy-load');
var lazyLoadThrottleTimeout;
function lazyLoad() {
if (lazyLoadThrottleTimeout) {
clearTimeout(lazyLoadThrottleTimeout);
}
lazyLoadThrottleTimeout = setTimeout(function() {
var scrollTop = window.pageYOffset;
lazyImages.forEach(function(lazyImage) {
if (lazyImage.offsetTop < (window.innerHeight + scrollTop)) {
// 替换data-src为src
if (lazyImage.dataset.src) {
lazyImage.src = lazyImage.dataset.src;
}
// 替换data-srcset为srcset
if (lazyImage.dataset.srcset) {
lazyImage.srcset = lazyImage.dataset.srcset;
}
// 加载完成后移除懒加载类
lazyImage.onload = function() {
lazyImage.classList.remove('lazy-load');
lazyImage.classList.add('lazy-loaded');
};
// 从数组中移除已处理的图片
lazyImages = Array.prototype.filter.call(lazyImages, function(image) {
return image !== lazyImage;
});
// 如果所有图片都已加载,移除滚动事件监听
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);
// 初始加载
lazyLoad();
}
// 添加CSS样式
var style = document.createElement('style');
style.textContent = `
img.lazy-load {
opacity: 0;
transition: opacity 0.3s;
}
img.lazy-loaded {
opacity: 1;
}
img.lazy-error {
opacity: 0.5;
filter: grayscale(100%);
}
`;
document.head.appendChild(style);
})();
</script>
<?php
}
add_action('wp_footer', 'add_lazy_load_script', 99);
CDN(内容分发网络)通过将静态资源(如图片、CSS、JavaScript)缓存到全球分布的边缘服务器上,使用户可以从地理位置上最近的服务器获取资源,从而显著减少延迟。
在functions.php中添加以下代码,将本地资源URL替换为CDN URL:
/**
* 配置WordPress使用CDN
*/
function setup_cdn_for_wordpress() {
// CDN配置
$cdn_config = array(
// 启用CDN
'enabled' => true,
// CDN域名(请替换为您的CDN域名)
'cdn_domain' => 'cdn.yourdomain.com',
// 本地域名(您的WordPress网站域名)
'local_domain' => $_SERVER['HTTP_HOST'],
// 要使用CDN的资源类型
'file_extensions' => array('jpg', 'jpeg', 'png', 'gif', 'webp', 'ico', 'svg', 'css', 'js', 'pdf', 'zip', 'mp4', 'mp3', 'woff', 'woff2', 'ttf', 'eot'),
// 排除的路径(某些路径下的资源不使用CDN)
'exclude_paths' => array('/wp-admin/', '/wp-includes/', '/wp-content/plugins/', '/wp-content/themes/'),
// 是否对管理员禁用CDN
'disable_for_admin' => true
);
// 如果CDN未启用,直接返回
if (!$cdn_config['enabled']) {
return;
}
// 对管理员禁用CDN
if ($cdn_config['disable_for_admin'] && current_user_can('manage_options')) {
return;
}
// 返回配置
return $cdn_config;
}
/**
* 将本地URL替换为CDN URL
*/
function replace_urls_with_cdn($url) {
// 获取CDN配置
$cdn_config = setup_cdn_for_wordpress();
// 如果没有配置或CDN未启用,返回原URL
if (!$cdn_config || !$cdn_config['enabled']) {
return $url;
}
// 解析URL
$parsed_url = parse_url($url);
// 如果不是HTTP/HTTPS协议,返回原URL
if (!isset($parsed_url['scheme']) || !in_array($parsed_url['scheme'], array('http', 'https'))) {
return $url;
}
// 检查主机名是否匹配本地域名
if (isset($parsed_url['host']) && $parsed_url['host'] === $cdn_config['local_domain']) {
// 检查路径是否在排除列表中
if (isset($parsed_url['path'])) {
foreach ($cdn_config['exclude_paths'] as $exclude_path) {
if (strpos($parsed_url['path'], $exclude_path) === 0) {
return $url;
}
}
}
// 检查文件扩展名
$path = isset($parsed_url['path']) ? $parsed_url['path'] : '';
$extension = pathinfo($path, PATHINFO_EXTENSION);
if (empty($extension) || !in_array(strtolower($extension), $cdn_config['file_extensions'])) {
return $url;
}
// 替换域名为CDN域名
$url = str_replace(
$cdn_config['local_domain'],
$cdn_config['cdn_domain'],
$url
);
}
return $url;
}
// 应用CDN替换到各种URL
add_filter('wp_get_attachment_url', 'replace_urls_with_cdn');
add_filter('the_content', 'cdn_replace_content_urls', 99);
add_filter('widget_text', 'cdn_replace_content_urls', 99);
add_filter('stylesheet_uri', 'replace_urls_with_cdn');
add_filter('script_loader_src', 'replace_urls_with_cdn');
add_filter('style_loader_src', 'replace_urls_with_cdn');
/**
* 替换内容中的URL为CDN URL
*/
function cdn_replace_content_urls($content) {
// 获取CDN配置
$cdn_config = setup_cdn_for_wordpress();
// 如果没有配置或CDN未启用,返回原内容
if (!$cdn_config || !$cdn_config['enabled']) {
return $content;
}
// 正则表达式匹配URL
$local_domain = preg_quote($cdn_config['local_domain'], '/');
$cdn_domain = $cdn_config['cdn_domain'];
// 匹配图片、CSS、JS等资源的URL
$pattern = '/https?://' . $local_domain . '/[^"'s]*.(' . implode('|', $cdn_config['file_extensions']) . ')(?:?[^"'s]*)?/i';
// 替换URL
$content = preg_replace_callback($pattern, function($matches) use ($cdn_config) {
$url = $matches[0];
// 检查路径是否在排除列表中
foreach ($cdn_config['exclude_paths'] as $exclude_path) {
if (strpos($url, $exclude_path) !== false) {
return $url;
}
}
// 替换域名为CDN域名
return str_replace(
'//' . $cdn_config['local_domain'],
'//' . $cdn_config['cdn_domain'],
$url
);
}, $content);
return $content;
}
现代CDN通常支持自动图片格式转换。以下代码可以检测浏览器是否支持WebP,并相应调整图片URL:
/**
* 根据浏览器支持自动提供WebP格式图片
*/
function provide_webp_when_supported($url, $attachment_id) {
// 获取CDN配置
$cdn_config = setup_cdn_for_wordpress();
// 如果没有配置或CDN未启用,返回原URL
if (!$cdn_config || !$cdn_config['enabled']) {
return $url;
}
// 检查URL是否已经是CDN URL
if (strpos($url, $cdn_config['cdn_domain']) === false) {
return $url;
}
// 检查文件扩展名
$extension = pathinfo($url, PATHINFO_EXTENSION);
$supported_extensions = array('jpg', 'jpeg', 'png');
if (!in_array(strtolower($extension), $supported_extensions)) {
return $url;
}
// 检查浏览器是否支持WebP
if (isset($_SERVER['HTTP_ACCEPT']) && strpos($_SERVER['HTTP_ACCEPT'], 'image/webp') !== false) {
// 在URL中添加WebP参数或修改扩展名
// 这取决于您的CDN提供商如何配置WebP转换
// 示例:在URL末尾添加?format=webp
if (strpos($url, '?') === false) {
$url .= '?format=webp';
} else {
$url .= '&format=webp';
}
}
return $url;
}
// 为图片URL添加WebP支持检测
add_filter('wp_get_attachment_url', 'provide_webp_when_supported', 10, 2);
add_filter('the_content', 'add_webp_support_to_content', 99);
/**
* 为内容中的图片添加WebP支持
*/
function add_webp_support_to_content($content) {
// 如果浏览器不支持WebP,直接返回
if (!isset($_SERVER['HTTP_ACCEPT']) || strpos($_SERVER['HTTP_ACCEPT'], 'image/webp') === false) {
return $content;
}
// 获取CDN配置
$cdn_config = setup_cdn_for_wordpress();
// 如果没有配置或CDN未启用,返回原内容
if (!$cdn_config || !$cdn_config['enabled']) {
return $content;
}
图片URL并添加WebP参数
$cdn_domain = preg_quote($cdn_config['cdn_domain'], '/');
$pattern = '/https?://' . $cdn_domain . '/[^"'s]*.(jpg|jpeg|png)(?:?[^"'s]*)?/i';
$content = preg_replace_callback($pattern, function($matches) {
$url = $matches[0];
// 添加WebP格式参数
if (strpos($url, '?') === false) {
return $url . '?format=webp';
} else {
return $url . '&format=webp';
}
}, $content);
return $content;
}
## 第四部分:集成响应式图片支持
### 4.1 WordPress响应式图片基础
WordPress 4.4+ 已内置响应式图片支持,但我们可以进一步优化:
/**
- 增强WordPress响应式图片功能
*/
function enhance_responsive_images($html, $attachment_id, $size, $icon, $attr) {
// 获取原始图片URL
$image_url = wp_get_attachment_url($attachment_id);
if (!$image_url) {
return $html;
}
// 获取图片元数据
$image_meta = wp_get_attachment_metadata($attachment_id);
if (!$image_meta) {
return $html;
}
// 获取CDN配置
$cdn_config = setup_cdn_for_wordpress();
// 如果是CDN URL,确保响应式图片srcset也使用CDN
if ($cdn_config && $cdn_config['enabled']) {
$html = str_replace(
'srcset="' . $cdn_config['local_domain'],
'srcset="' . $cdn_config['cdn_domain'],
$html
);
}
// 添加懒加载属性
$html = preg_replace('/<img(.*?)src=/', '<img$1data-src=', $html);
$html = preg_replace('/srcset=/', 'data-srcset=', $html);
// 添加懒加载类
if (strpos($html, 'class="') !== false) {
$html = preg_replace('/class="(.*?)"/', 'class="$1 lazy-load"', $html);
} else {
$html = preg_replace('/<img/', '<img class="lazy-load"', $html);
}
// 添加noscript回退
$noscript_html = preg_replace('/data-src=/', 'src=', $html);
$noscript_html = preg_replace('/data-srcset=/', 'srcset=', $noscript_html);
$noscript_html = preg_replace('/class="(.*?)lazy-load(.*?)"/', 'class="$1$2"', $noscript_html);
$html .= '<noscript>' . $noscript_html . '</noscript>';
return $html;
}
// 应用增强的响应式图片功能
add_filter('wp_get_attachment_image', 'enhance_responsive_images', 10, 5);
### 4.2 自定义图片尺寸生成
/**
- 添加自定义图片尺寸用于响应式设计
*/
function add_custom_image_sizes() {
// 添加各种设备适用的图片尺寸
add_image_size('retina_large', 1920, 0, false); // 大屏Retina设备
add_image_size('desktop_large', 1200, 0, false); // 桌面大屏
add_image_size('desktop_medium', 800, 0, false); // 桌面中屏
add_image_size('tablet_large', 600, 0, false); // 平板大屏
add_image_size('tablet_small', 400, 0, false); // 平板小屏
add_image_size('mobile_large', 300, 0, false); // 手机大屏
add_image_size('mobile_small', 150, 0, false); // 手机小屏
}
add_action('after_setup_theme', 'add_custom_image_sizes');
/**
- 自定义图片尺寸的srcset
*/
function custom_image_srcset($sources, $size_array, $image_src, $image_meta, $attachment_id) {
// 获取CDN配置
$cdn_config = setup_cdn_for_wordpress();
// 自定义尺寸映射
$custom_sizes = array(
'retina_large' => 1920,
'desktop_large' => 1200,
'desktop_medium' => 800,
'tablet_large' => 600,
'tablet_small' => 400,
'mobile_large' => 300,
'mobile_small' => 150
);
foreach ($custom_sizes as $size_name => $width) {
// 检查是否有该尺寸的图片
if (isset($image_meta['sizes'][$size_name])) {
$image_url = wp_get_attachment_image_url($attachment_id, $size_name);
// 应用CDN
if ($cdn_config && $cdn_config['enabled']) {
$image_url = replace_urls_with_cdn($image_url);
}
$sources[$width] = array(
'url' => $image_url,
'descriptor' => 'w',
'value' => $width,
);
}
}
// 按宽度排序
ksort($sources);
return $sources;
}
add_filter('wp_calculate_image_srcset', 'custom_image_srcset', 10, 5);
## 第五部分:性能优化与缓存策略
### 5.1 浏览器缓存优化
/**
- 添加浏览器缓存头
*/
function add_cache_headers() {
// 如果不是管理页面
if (!is_admin()) {
// 设置静态资源缓存时间(1年)
$cache_time = 31536000; // 60*60*24*365
// 获取当前请求的扩展名
$request_uri = $_SERVER['REQUEST_URI'];
$extension = pathinfo($request_uri, PATHINFO_EXTENSION);
// 静态资源扩展名列表
$static_extensions = array(
'jpg', 'jpeg', 'png', 'gif', 'webp', 'ico', 'svg',
'css', 'js', 'pdf', 'zip', 'mp4', 'mp3',
'woff', 'woff2', 'ttf', 'eot'
);
if (in_array(strtolower($extension), $static_extensions)) {
header("Cache-Control: public, max-age={$cache_time}, immutable");
header("Expires: " . gmdate('D, d M Y H:i:s', time() + $cache_time) . ' GMT');
// 添加ETag
$etag = md5($request_uri . filemtime(ABSPATH . $request_uri));
header("ETag: {$etag}");
}
}
}
add_action('send_headers', 'add_cache_headers');
### 5.2 资源预加载与预连接
/**
- 添加资源提示(Resource Hints)
*/
function add_resource_hints() {
// 获取CDN配置
$cdn_config = setup_cdn_for_wordpress();
if ($cdn_config && $cdn_config['enabled']) {
// 预连接到CDN域名
echo '<link rel="preconnect" href="https://' . esc_attr($cdn_config['cdn_domain']) . '" crossorigin>';
// DNS预获取
echo '<link rel="dns-prefetch" href="//' . esc_attr($cdn_config['cdn_domain']) . '">';
}
// 预加载关键资源
echo '<link rel="preload" href="' . get_template_directory_uri() . '/assets/css/critical.css" as="style">';
echo '<link rel="preload" href="' . get_template_directory_uri() . '/assets/js/lazyload.js" as="script">';
}
add_action('wp_head', 'add_resource_hints', 1);
## 第六部分:监控与调试功能
### 6.1 性能监控
/**
- 添加性能监控
*/
class PerformanceMonitor {
private $start_time;
private $queries = array();
public function __construct() {
$this->start_time = microtime(true);
// 监控数据库查询
if (defined('SAVEQUERIES') && SAVEQUERIES) {
add_filter('query', array($this, 'log_query'));
}
}
public function log_query($query) {
$this->queries[] = array(
'query' => $query,
'time' => microtime(true)
);
return $query;
}
public function get_performance_data() {
$end_time = microtime(true);
$load_time = ($end_time - $this->start_time) * 1000; // 转换为毫秒
$data = array(
'load_time' => round($load_time, 2),
'memory_usage' => round(memory_get_peak_usage() / 1024 / 1024, 2),
'query_count' => count($this->queries),
'cdn_enabled' => false
);
// 检查CDN状态
$cdn_config = setup_cdn_for_wordpress();
if ($cdn_config && $cdn_config['enabled']) {
$data['cdn_enabled'] = true;
$data['cdn_domain'] = $cdn_config['cdn_domain'];
}
return $data;
}
}
// 初始化性能监控
$performance_monitor = new PerformanceMonitor();
/**
- 在页脚显示性能数据(仅管理员可见)
*/
function display_performance_data() {
global $performance_monitor;
if (current_user_can('manage_options')) {
$data = $performance_monitor->get_performance_data();
echo '<div style="position:fixed;bottom:10px;right:10px;background:rgba(0,0,0,0.8);color:#fff;padding:10px;font-size:12px;z-index:9999;border-radius:5px;">';
echo '<strong>性能数据:</strong><br>';
echo '加载时间: ' . $data['load_time'] . 'ms<br>';
echo '内存使用: ' . $data['memory_usage'] . 'MB<br>';
echo '数据库查询: ' . $data['query_count'] . '<br>';
echo 'CDN: ' . ($data['cdn_enabled'] ? '已启用 (' . $data['cdn_domain'] . ')' : '未启用');
echo '</div>';
}
}
add_action('wp_footer', 'display_performance_data');
### 6.2 图片加载错误处理
/**
- 图片加载错误处理
*/
function handle_image_errors() {
?>
<script>
document.addEventListener('DOMContentLoaded', function() {
// 监听图片加载错误
document.addEventListener('error', function(e) {
if (e.target.tagName === 'IMG') {
var img = e.target;
// 如果是懒加载图片
if (img.classList.contains('lazy-load')) {
// 尝试加载原始src(非CDN版本)
var originalSrc = img.dataset.src;
if (originalSrc) {
// 移除CDN域名,尝试加载原始图片
var localSrc = originalSrc.replace('cdn.yourdomain.com', 'yourdomain.com');
img.src = localSrc;
// 标记为回退加载
img.dataset.fallback = 'true';
}
}
// 添加错误类
img.classList.add('image-error');
// 可选:显示占位图
if (!img.dataset.placeholderSet) {
img.style.backgroundColor = '#f0f0f0';
img.style.minHeight = '100px';
img.dataset.placeholderSet = 'true';
}
}
}, true); // 使用捕获阶段
});
</script>
<style>
.image-error {
opacity: 0.5;
filter: grayscale(100%);
}
.image-error::after {
content: '图片加载失败';
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
color: #999;
font-size: 12px;
}
</style>
<?php
}
add_action('wp_footer', 'handle_image_errors');
## 第七部分:完整集成与配置
### 7.1 创建配置页面
/**
- 创建懒加载和CDN配置页面
*/
class LazyLoadCDN_Settings {
public function __construct() {
add_action('admin_menu', array($this, 'add_admin_menu'));
add_action('admin_init', array($this, 'settings_init'));
}
public function add_admin_menu() {
add_options_page(
'懒加载与CDN设置',
'图片优化',
'manage_options',
'lazyload-cdn-settings',
array($this, 'settings_page')
);
}
public function settings_init() {
register_setting('lazyload_cdn', 'lazyload_cdn_settings');
add_settings_section(
'lazyload_cdn_section',
'懒加载与CDN配置',
array($this, 'settings_section_callback'),
'lazyload_cdn'
);
// CDN域名设置
add_settings_field(
'cdn_domain',
'CDN域名',
array($this, 'cdn_domain_render'),
'lazyload_cdn',
'lazyload_cdn_section'
);
// 懒加载启用设置
add_settings_field(
'lazyload_enabled',
'启用懒加载',
array($this, 'lazyload_enabled_render'),
'lazyload_cdn',
'lazyload_cdn_section'
);
// WebP支持设置
add_settings_field(
'webp_support',
'启用WebP支持',
array($this, 'webp_support_render'),
'lazyload_cdn',
'lazyload_cdn_section'
);
// 排除路径设置
add_settings_field(
'exclude_paths',
'排除路径',
array($this, 'exclude_paths_render'),
'lazyload_cdn',
'lazyload_cdn_section'
);
}
public function cdn_domain_render() {
$options = get_option('lazyload_cdn_settings');
?>
<input type="text" name="lazyload_cdn_settings[cdn_domain]"
value="<?php echo isset($options['cdn_domain']) ? esc_attr($options['cdn_domain']) : ''; ?>"
placeholder="cdn.yourdomain.com">
<p class="description">请输入您的CDN域名,例如:cdn.yourdomain.com</p>
<?php
}
public function lazyload_enabled_render() {
$options = get_option('lazyload_cdn_settings');
?>
<input type="checkbox" name="lazyload_cdn_settings[lazyload_enabled]"
value="1" <?php checked(isset($options['lazyload_enabled']) && $options['lazyload_enabled']); ?>>
<label>启用图片懒加载功能</label>
<?php
}
public function webp_support_render() {
$options = get_option('lazyload_cdn_settings');
?>
<input type="checkbox" name="lazyload_cdn_settings[webp_support]"
value="1" <?php checked(isset($options['webp_support']) && $options['webp_support']); ?>>
<label>为支持WebP的浏览器自动提供WebP格式图片</label>
<?php
}
public function exclude_paths_render() {
$options = get_option('lazyload_cdn_settings');
$paths = isset($options['exclude_paths']) ? $options['exclude_paths'] : "/wp-admin/n/wp-includes/";
?>
<textarea name="lazyload_cdn_settings[exclude_paths]"
rows="5" cols="50"><?php echo esc_textarea($paths); ?></textarea>
<p class="description">每行一个路径,这些路径下的资源将不使用CDN</p>
<?php
}
public function settings_section_callback() {
echo '配置图片懒加载和CDN加速功能';
}
public function settings_page() {
?>
<div class="wrap">
<h1>懒加载与CDN设置</h1>
<form action="options.php" method="post">
<?php
settings_fields('lazyload_cdn');
do_settings_sections('lazyload_cdn');
submit_button();
?>
</form>
<div class="card">
<h2>使用说明</h2>
<ol>
<li>配置CDN域名后,所有静态资源将通过CDN加速</li>
<li>懒加载功能会延迟加载非视口内的图片</li>
<li>WebP支持会自动为兼容浏览器提供更小的图片格式</li>
<li>保存设置后,请清除缓存以查看效果</li>
</ol>
</div>
</div>
<?php
}
}
// 初始化设置页面
if (is_admin()) {
new LazyLoadCDN_Settings();
}
### 7.2 更新配置获取函数
/**
- 更新CDN配置获取函数,


