WordPress 头像加载优化:用昵称首字母替代 Gravatar
![]()
本文介绍一种与具体主题无关的 WordPress 头像优化方案:网站作者继续使用真实头像,其他注册用户和评论访客统一使用昵称首字母生成头像,从而减少对 Gravatar 等第三方服务的依赖。
一、背景
WordPress 默认使用 Gravatar 提供用户头像。主题调用 get_avatar() 后,WordPress 通常会生成类似下面的图片地址:
https://secure.gravatar.com/avatar/...
这个方案使用简单,但个人网站可能遇到两个问题:
1. Gravatar 属于第三方服务,网络连接不稳定时,头像请求可能长时间等待或超时;
2. 首页、评论列表等页面会同时加载多张头像,多个外部请求会进一步影响页面加载体验。
本文示例的基础运行环境为:
- WordPress 5.8;
- PHP 7.2.13。
方案基于 WordPress 官方头像过滤器实现,不依赖某一款特定主题。优化目标是:
- 网站作者保留真实头像;
- 其他用户不再请求 Gravatar;
- 普通用户头像由昵称首字符生成;
- 相同昵称始终使用相同背景色;
- 兼容传统 WordPress 主题和 REST API;
- 兼容 WordPress 5.8 与 PHP 7.2.13。
二、问题定位
-Gravatar 请求拖慢页面
通过浏览器开发者工具的 Network 面板,可以搜索:
gravatar
avatar
secure.gravatar.com
如果头像地址来自 Gravatar,页面渲染就依赖第三方服务。即使头像不是首屏主要内容,连
接等待仍可能影响页面体验。
因此,这次优化没有继续尝试更换另一个公共头像镜像,而是直接取消普通用户头像的外部请求。
三、方案设计
本次优化分为两步。
第一步:重写 WordPress 头像输出
通过 WordPress 的pre_get_avatar过滤器,在 WordPress 请求 Gravatar 之前接管头像 HTML:
- 如果是指定的网站作者,输出媒体库中的本地真实头像;
- 如果是其他用户,提取昵称首字符,生成 SVG 头像;
- SVG 经过 URL 编码后直接写入
img src="data:image/svg+xml,..."; - 浏览器不再为普通用户头像发起网络请求。
之所以继续输出标准<img>,而不是改成<span>,是为了兼容现有主题中已有的选择器:
img.avatar
.comment-author img
.avatar-64
第二步:同步处理 REST API 头像
如果网站采用前后端分离架构,还需要过滤 WordPress REST API 返回的评论和用户头像地址,把普通用户的 author_avatar_urls 或 avatar_urls 替换成相同的内联 SVG Data URL。
这样,无论页面由传统 PHP 主题渲染,还是由 React、Vue 等前端应用渲染,普通用户头像都不需要请求 Gravatar。
四、具体实现
1. 配置作者信息
插件中配置需要保留真实头像的作者用户 ID,以及媒体库头像地址:
const WPNIA_AUTHOR_USER_ID = 1;
const WPNIA_AUTHOR_AVATAR_URL =
'https://example.com/wp-content/uploads/author-avatar.webp';
作者用户 ID 可以在以下位置查找:
WordPress 后台 → 用户 → 所有用户 → 打开作者资料
查看浏览器地址中的 user_id=数字 即可。
作者头像建议上传到自己的 WordPress 媒体库,避免作者头像继续依赖 Gravatar。
2. 解析头像对象中的用户身份
get_avatar() 的第一个参数可能有多种类型,因此需要分别处理:
function wpnia_resolve_identity($id_or_email) {
$user_id = 0;
$name = '';
if ($id_or_email instanceof WP_User) {
$user_id = (int) $id_or_email->ID;
$name = $id_or_email->display_name;
} elseif ($id_or_email instanceof WP_Comment) {
$user_id = (int) $id_or_email->user_id;
$name = $id_or_email->comment_author;
} elseif ($id_or_email instanceof WP_Post) {
$user_id = (int) $id_or_email->post_author;
$user = get_user_by('id', $user_id);
if ($user) {
$name = $user->display_name;
}
} elseif (is_numeric($id_or_email)) {
$user_id = (int) $id_or_email;
$user = get_user_by('id', $user_id);
if ($user) {
$name = $user->display_name;
}
}
return array(
'user_id' => $user_id,
'name' => sanitize_text_field(wp_strip_all_tags($name)),
);
}
这里使用传统数组语法,没有使用 PHP 7.4 以上版本才支持的语法,所以能够兼容 PHP 7.2.13。
3. 获取昵称首字符
中文昵称需要按 UTF-8 字符截取,不能直接使用 substr($name, 0, 1),否则可能截断中文字符的字节。
function wpnia_initial($name) {
$name = trim(preg_replace('/\\s+/u', ' ', $name));
if ('' === $name) {
return '?';
}
if (function_exists('mb_substr')) {
return mb_strtoupper(
mb_substr($name, 0, 1, 'UTF-8'),
'UTF-8'
);
}
if (preg_match('/^./u', $name, $match)) {
return strtoupper($match[0]);
}
return strtoupper(substr($name, 0, 1));
}
优先使用 mb_substr();服务器没有启用 mbstring 扩展时,再使用 Unicode 正则获取完整的第一个字符。
4. 根据昵称生成稳定背景色
为了避免每次刷新时颜色变化,可以使用昵称的 CRC32 结果选择固定颜色:
function wpnia_color($name) {
$palette = array(
'#2563EB',
'#7C3AED',
'#DB2777',
'#059669',
'#D97706',
'#DC2626',
'#0891B2',
'#4F46E5',
);
$index = abs(crc32(strtolower($name))) % count($palette);
return $palette[$index];
}
相同昵称经过相同计算后,会稳定地映射到同一种颜色。
5. 生成零请求SVG头像
function wpnia_data_url($name) {
$svg = sprintf(
'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 96 96">' .
'<rect width="96" height="96" rx="48" fill="%1$s"/>' .
'<text x="48" y="50" text-anchor="middle" ' .
'dominant-baseline="central" fill="#fff" ' .
'font-family="Arial,sans-serif" font-size="40" ' .
'font-weight="600">%2$s</text></svg>',
esc_attr(wpnia_color($name)),
esc_html(wpnia_initial($name))
);
return 'data:image/svg+xml,' . rawurlencode($svg);
}
生成结果直接放入图片的 src 属性:
img src="data:image/svg+xml,..." alt="张三 avatar"
虽然它仍然是图片元素,但是不再需要请求服务器或第三方头像服务。
6. 使用 pre_get_avatar 接管头像
function wpnia_avatar_html($avatar, $id_or_email, $args) {
if (emptyempty($args['force_display']) && !get_option('show_avatars')) {
return $avatar;
}
$identity = wpnia_resolve_identity($id_or_email);
$size = isset($args['size'])
? max(16, absint($args['size']))
: 96;
if ((int) $identity['user_id'] === WPNIA_AUTHOR_USER_ID) {
return sprintf(
'<img class="avatar avatar-%1$d photo" ' .
'src="%2$s" alt="%3$s" width="%1$d" height="%1$d" ' .
'loading="lazy" decoding="async" />',
$size,
esc_url(WPNIA_AUTHOR_AVATAR_URL),
esc_attr($identity['name'])
);
}
$name = $identity['name'] ?: __('User', 'wpnia');
return sprintf(
'<img class="avatar avatar-%1$d photo wpnia-initial-avatar" ' .
'src="%2$s" alt="%3$s" width="%1$d" height="%1$d" ' .
'loading="lazy" decoding="async" />',
$size,
esc_attr(wpnia_data_url($name)),
esc_attr(sprintf(__('%s avatar', 'wpnia'), $name))
);
}
add_filter('pre_get_avatar', 'wpnia_avatar_html', 10, 3);
这里还增加了:
- 固定
width和height,减少布局偏移; loading="lazy",让非首屏头像延迟加载;decoding="async",避免图片解码阻塞页面主线程。
7. REST API 的处理
如果网站使用 React、Vue 等前后端分离架构,WordPress REST API 返回的字段仍可能包含 Gravatar 地址:
{
"author_avatar_urls": {
"24": "https://secure.gravatar.com/avatar/...",
"48": "https://secure.gravatar.com/avatar/...",
"96": "https://secure.gravatar.com/avatar/..."
}
}
因此还需要过滤:
rest_prepare_comment;rest_prepare_user。
将普通用户的 author_avatar_urls 或 avatar_urls 替换成同一个内联 SVG Data URL。这样,无论页面由 PHP 主题渲染,还是由前端调用 REST API 渲染,都不会再次请求 Gravatar。
五、验证结果
修改完成后,可以按以下步骤验证。
1. 检查头像 DOM
普通用户头像应继续使用标准的 img class="avatar" 结构,头像地址应以此开头:
data:image/svg+xml,
2. 检查网络请求
打开浏览器开发者工具,在 Network 面板搜索:
gravatar
普通用户头像不应再产生 Gravatar 请求。如果作者也配置了媒体库头像,整个页面就不需要依赖 Gravatar。
3. 检查各个页面入口
- 至少验证以下位置:
- 文章评论区;
- 用户资料或作者信息区域;
- 主题中所有调用 WordPress 标准头像函数的位置;
- 移动端页面;
- REST API 评论和用户列表(如果使用前后端分离)。
4. 清理缓存
修改主题或插件代码后,需要清理:
- WordPress 页面缓存;
- 对象缓存;
- CDN 缓存;
- 浏览器缓存。
否则可能仍然看到修改前的头像 HTML。
本次代码已经通过 PHP 7 模式语法解析,目标兼容 WordPress 5.8 和 PHP 7.2.13;正式部署前仍应在测试环境检查主题、缓存插件及 CSP 配置。由于没有在线生产环境性能数据,本文不虚构具体毫秒数;实际收益应以浏览器 Network 和 Lighthouse 测试为准。
六、效果与收益
通过这次改造后,头像体系变为:
![]()
| 用户类型 | 头像来源 | 是否产生外部请求 |
|---|---|---|
| 网站作者 | WordPress 媒体库本地头像 | 否 |
| 注册用户 | 昵称首字符 SVG | 否 |
| 评论访客 | 昵称首字符 SVG | 否 |
| REST API 普通用户 | 内联 SVG Data URL | 否 |
七、经验总结
头像加载问题的核心是资源来源不可控:Gravatar 属于第三方服务,网络延迟和可用性不是由自己的站点掌控。 与其继续更换公共镜像,不如从源头减少普通用户头像的远程依赖。所以更完整的通用方案是:
- 普通用户头像使用昵称首字符本地生成;
- 作者头像存放在自己的媒体库;
- 继续使用 WordPress 标准头像过滤器和
img class="avatar"结构; - REST API 同步替换头像地址;
- 最后通过 DOM、Network 和多个页面入口进行验证。
最后
PHP 7.2 已停止安全维护。上述代码可以兼容 PHP 7.2.13,但这只是兼容性处理,旧版本不一定安全。如果条件允许,还是建议先在测试环境验证主题与插件,再升级到仍受支持的 PHP 版本。
插件下载地址(开箱即用)