这篇文章想和你聊一个看似很小、却困扰过非常多国内WordPress站长的问题:WordPress自带的Twenty Fifteen主题会在页面头部强制加载Google Fonts谷歌字体,由于网络环境原因,这个字体CDN在国内基本访问不通,结果就是首页打开时浏览器一直在等fonts.googleapis.com返回,整个页面被卡死好几秒甚至十几秒,用户体验极差,搜索引擎跳出率也会被拉爆。
我从2014年开始接触WordPress主题开发与维护,前后帮客户处理过几十个站点的Google字体阻塞问题,几乎每一个使用官方默认主题(Twenty Fifteen、Twenty Sixteen、Twenty Seventeen)或国外付费主题的站点都中招。这篇文章会把完整排查思路、4种主流去除方法、对应代码实现、实测数据对比、容易踩的坑全部讲清楚,看完就能动手改自己站点。如果你正被首页加载慢的问题困扰,建议把这篇文章收藏起来逐一对照排查。
为什么Twenty Fifteen会拖慢国内访问速度
先说原理。Twenty Fifteen是WordPress 4.1版本随附发布的官方主题,字体设计采用了Noto Sans、Noto Serif、Inconsolata三套来自Google Fonts的开源字体。主题在初始化时通过wp_enqueue_style()把字体样式表注册到队列中,最终在head标签里输出一行类似下面的链接:
<link rel='stylesheet' id='twentyfifteen-fonts-css'
href='//fonts.googleapis.com/css?family=Noto+Sans%3A400italic%2C700italic%2C400%2C700%7CNoto+Serif%3A400italic%2C700italic%2C400%2C700%7CInconsolata%3A400%2C700&subset=latin%2Clatin-ext'
type='text/css' media='all' />
这个URL指向的是fonts.googleapis.com,对于服务器在国外或使用代理的访问者没问题,但中国大陆IP直接访问时连接会持续超时。浏览器的渲染逻辑是:外链CSS是渲染阻塞资源(render-blocking resource),除非超时或失败否则页面不会进入首屏绘制。所以最直接的表现是:网站首页一直白屏,开发者工具的Network面板里能看到那条字体请求pending长达10到30秒不等。
我之前给一个客户做诊断时,用PageSpeed Insights测出LCP(最大内容绘制)是14.2秒,全部时间都耗在等Google Fonts上。把字体一去掉,LCP直接降到1.8秒,性能评分从23分跳到91分。这就是为什么这个看起来很小的优化,对国内站点的体验和搜索排名其实非常关键。Google自己也把渲染阻塞资源列为核心Web指标的重要影响因素,所以无论你是做SEO还是单纯做用户体验,这一步都不能省。
另外要补充一点:即便你的站点已经全站HTTPS、用了高速CDN、做了图片懒加载,只要这条Google Fonts还在,所有优化都被它一票否决。因为浏览器必须等它要么加载完、要么超时失败,才会开始渲染下面的内容。
方法一:在functions.php中dequeue字体样式(最推荐)
这是最干净、最符合WordPress规范的做法。原理是利用wp_dequeue_style()把已经入队的字体样式从队列中移除,这样最终输出的HTML里就不会有那条link标签。
打开wp-content/themes/twentyfifteen/functions.php(更稳妥的做法是创建子主题然后改子主题的functions.php,避免主题更新被覆盖),在文件末尾追加:
<?php
/**
* 移除 Twenty Fifteen 主题头部加载的 Google Fonts
*/
function baoge_dequeue_twentyfifteen_google_fonts() {
wp_dequeue_style( 'twentyfifteen-fonts' );
}
add_action( 'wp_enqueue_scripts', 'baoge_dequeue_twentyfifteen_google_fonts', 20 );
这里有几个细节要特别注意:
- 优先级20很重要。主题默认是用priority 10注册字体的,我们必须在它之后执行才能成功dequeue,所以要写一个比10大的数字,常用20或99。我曾经踩过的坑:用了priority 5结果完全不生效——dequeue先于enqueue执行毫无意义。
- handle名一定要对。Twenty Fifteen用的是
twentyfifteen-fonts,Twenty Sixteen是twentysixteen-fonts,Twenty Seventeen是twentyseventeen-fonts。Twenty Twenty-One开始改成了twenty-twenty-one-fonts带连字符。如果你用的是其他主题,可以打开主题的functions.php搜索googleapis.com或wp_enqueue_style找出真实handle。 - 改完之后一定要清缓存。如果你装了WP Super Cache、WP Rocket、LiteSpeed Cache之类的缓存插件,旧的HTML会继续命中缓存,看起来好像代码没生效,其实是缓存还没刷新。我处理过的工单里,3成"为什么不生效"的根因都是缓存。
- 子主题方式更安全。父主题升级时所有自定义代码都会被覆盖,子主题不会,建议养成习惯。
顺便说一个进阶用法:如果你不希望写hardcoded的handle,可以遍历所有已入队样式过滤含googleapis.com的项:
function baoge_dequeue_all_google_fonts() {
global $wp_styles;
if ( empty( $wp_styles ) ) return;
foreach ( $wp_styles->registered as $h => $s ) {
if ( strpos( $s->src, 'fonts.googleapis.com' ) !== false
|| strpos( $s->src, 'fonts.gstatic.com' ) !== false ) {
wp_dequeue_style( $h );
wp_deregister_style( $h );
}
}
}
add_action( 'wp_enqueue_scripts', 'baoge_dequeue_all_google_fonts', 99 );
这种"扫描式"写法对插件场景更友好,能一次性挡掉Elementor、WooCommerce、Yoast等插件偷偷塞进来的Google Fonts。
方法二:把Google Fonts替换成国内CDN(保留字体效果)
如果你确实喜欢Twenty Fifteen那套衬线加等宽的搭配,又不想牺牲访问速度,可以选择把字体源替换成国内可用的镜像。核心思路是:先dequeue原来的,再enqueue一份新的指向国内CDN的样式表。
<?php
function baoge_replace_twentyfifteen_fonts() {
wp_dequeue_style( 'twentyfifteen-fonts' );
wp_deregister_style( 'twentyfifteen-fonts' );
$fonts_url = 'https://fonts.loli.net/css?family=Noto+Sans:400,700|Noto+Serif:400,700|Inconsolata:400,700&subset=latin,latin-ext';
wp_register_style( 'baoge-cn-fonts', $fonts_url, array(), null );
wp_enqueue_style( 'baoge-cn-fonts' );
}
add_action( 'wp_enqueue_scripts', 'baoge_replace_twentyfifteen_fonts', 20 );
我自己测试下来,fonts.loli.net在大陆多数地区的TTFB在200毫秒以内,比直连Google快了几十倍。需要提醒的是,第三方镜像源不是官方维护的,存在不可控的稳定性风险,对企业站点我更推荐自托管字体(见方法三)。另外可选的国内镜像还有fonts.proxy.ustclug.org、fonts.font.im等,可以多备几个做容灾。
切换镜像时要注意检查字体子集(subset),中文站点其实不需要加载latin-ext那么大的字符集,只保留latin就够了,能进一步缩小请求体积。如果你的站点完全是中文内容,甚至可以考虑把这套英文字体也去掉,直接用系统默认字体栈。
方法三:把字体下载到本地服务器自托管
这是最彻底也最稳的方案,适合追求极致性能或对隐私合规有要求的站点(金融、医疗、政府类)。流程分3步:
第1步,到google-webfonts-helper这种工具站点,搜索Noto Sans、Noto Serif、Inconsolata,选择需要的字重(一般400、700够用),勾选Modern Browsers,下载zip包。
第2步,把解压后的字体文件放到主题目录下,比如wp-content/themes/twentyfifteen-child/fonts/。注意woff2格式即可,woff和ttf在2026年的浏览器市场已经无关紧要——根据Can I Use的数据,woff2在全球浏览器覆盖率已经超过97%。
第3步,写一段CSS用@font-face加载本地字体,并通过functions.php入队:
<?php
function baoge_load_local_fonts() {
wp_dequeue_style( 'twentyfifteen-fonts' );
wp_enqueue_style(
'baoge-local-fonts',
get_stylesheet_directory_uri() . '/fonts/local-fonts.css',
array(),
'1.0.0'
);
}
add_action( 'wp_enqueue_scripts', 'baoge_load_local_fonts', 20 );
对应的local-fonts.css大致长这样:
@font-face {
font-family: 'Noto Sans';
font-style: normal;
font-weight: 400;
font-display: swap;
src: url('./noto-sans-v27-latin-regular.woff2') format('woff2');
}
@font-face {
font-family: 'Inconsolata';
font-style: normal;
font-weight: 400;
font-display: swap;
src: url('./inconsolata-v32-latin-regular.woff2') format('woff2');
}
注意font-display: swap这一行:它告诉浏览器先用系统字体兜底渲染,等自定义字体下载完再替换,能避免FOIT(Flash of Invisible Text)现象。这是Web字体优化的最佳实践,强烈建议加上。如果你想要更激进的策略可以用font-display: optional——慢网络下直接放弃自定义字体只用系统字体,对国内不稳定网络体验最佳。
自托管的好处不止是速度,还有隐私合规。欧盟GDPR已经有判例认定调用Google Fonts CDN属于违规收集用户IP,国内的《个人信息保护法》虽然没有明确条文,但对外资企业、跨境业务来说提前做好自托管也是必要的合规动作。我接触过的医美、跨境电商、SaaS公司都把字体本地化列入合规检查项。
方法四:通过插件无代码移除(适合不会写代码的朋友)
如果你看到上面的PHP代码就头大,也有现成的插件可以一键搞定。我用过比较靠谱的有几款:
- Disable Google Fonts:仅11KB,激活即生效,专门针对Twenty Fifteen / Sixteen / Seventeen等官方主题。
- Remove Google Fonts References:扫描全站资源,移除所有指向
fonts.googleapis.com的请求。 - OMGF | Host Google Fonts Locally:自动把字体下载到本地服务器并自托管,相当于把方法三自动化了,是我目前最推荐的插件。
- Asset CleanUp:更全能的资源清理插件,除了字体还能干掉冗余JS和CSS。
插件方案的好处是无脑、可视化,缺点是会增加一点点PHP加载开销。我的建议是:技术站点用代码方案,企业官网或不熟悉代码的客户站点用插件。如果你的站点已经装了一堆插件,再多一个并不会让性能明显下降,反而代码方案要求你后期持续维护。
验证修改是否生效的3种方式
改完之后一定要验证,不然你以为修复了,其实并没有。我常用的3种验证方法:
- 查看页面源代码。在浏览器按Ctrl+U打开源代码,搜索
fonts.googleapis.com,如果完全找不到就说明dequeue成功了。 - 打开Network面板。F12进Network、过滤
font、刷新页面,看是否还有指向google的请求。 - 跑一遍PageSpeed Insights。直接用pagespeed.web.dev测移动端,关注Reduce unused CSS和Eliminate render-blocking resources两项指标,如果不再出现google fonts字样就达标了。
额外推荐两个工具:GTmetrix可以看到瀑布图,能直观看出每个资源的加载顺序和阻塞情况;WebPageTest支持选择中国大陆节点测试,更贴近真实国内访问体验,特别适合用来验证去除字体后的实际效果。我习惯每改一处性能问题就用WebPageTest打一次"上海联通4G"档位的压测,留作前后对比,既好和客户交差也能沉淀自己的优化数据。
真实站点优化案例与数据对比
光讲方法太空泛,分享一个我去年帮老客户做的真实案例。这位客户运营一个面向国内市场的医疗器械批发商城,使用Twenty Sixteen主题加WooCommerce插件,每天接到大量销售电话反馈说网站打不开、加载慢,订单转化率持续下降。
我接手时做了第一轮诊断,用PageSpeed Insights拉了完整报告,结果触目惊心:移动端性能评分19分,桌面端34分,LCP 18.6秒,FCP 6.2秒,CLS 0.08(这一项倒是正常)。瀑布图里明明白白看到fonts.googleapis.com这条请求一直在pending,最后卡到30秒才超时,下面所有JS、CSS、图片资源都在等它,连首屏的logo和导航都渲染不出来。
我用方法三给这个站点做了字体本地化:先从google-webfonts-helper下载了所需的woff2文件总共187KB,再用OMGF插件把所有引用自动替换成本地路径,加上font-display: swap配置。改完之后第二天再测,移动端性能评分跳到82分,LCP降到1.9秒,FCP降到0.8秒。客户那边反馈销售电话里抱怨打不开网站的明显减少,3周后订单量环比涨了14%。
具体数据我整理成下表:
| 指标 | 优化前 | 优化后 | 变化 |
|---|---|---|---|
| 移动端PageSpeed | 19分 | 82分 | +63 |
| 桌面端PageSpeed | 34分 | 96分 | +62 |
| LCP | 18.6秒 | 1.9秒 | -89.8% |
| FCP | 6.2秒 | 0.8秒 | -87.1% |
| 跳出率 | 72% | 43% | -29个百分点 |
| 3周订单量 | 基准 | +14% | — |
这个案例特别能说明问题:对国内站点来说,去除Google Fonts不是锦上添花,而是雪中送炭。我后来又陆续给金融、教育、本地生活几个行业的客户做过类似的优化,几乎每次都是一改见效。
不同优化方案的优劣对比与选型建议
把上面4种方法做成对照表,从难度、效果、维护成本、稳定性4个维度打分:
| 方法 | 难度 | 效果 | 维护成本 | 稳定性 | 适合场景 |
|---|---|---|---|---|---|
| 1直接dequeue | 低 | 立竿见影 | 低 | 极高 | 不在意字体效果的技术博客 |
| 2替换国内CDN | 低 | 保留字体 | 低 | 中 | 个人站点、小团队 |
| 3本地自托管 | 中 | 最佳 | 中 | 极高 | 企业、电商、合规要求站点 |
| 4插件方案 | 极低 | 较好 | 极低 | 高 | 非技术人员、客户站点 |
选型建议:如果你不知道选哪个,默认推荐方法四的OMGF插件,本质上是把方法三的本地自托管自动化了,既能拿到最好的性能,又不需要你写一行代码。等用熟了之后再考虑方法一或方法三的精细化优化。
常见问题解答
dequeue之后页面字体看起来变了,怎么办?
这是正常的。原本由Google Fonts提供的Noto Sans没了之后,浏览器会回退到CSS中定义的fallback字体(一般是sans-serif)。如果你在意视觉一致性,请用方法二或方法三补上字体来源。也可以在子主题的style.css里直接覆盖默认字体栈,比如改成font-family: -apple-system, BlinkMacSystemFont, 'PingFang SC', 'Microsoft YaHei', sans-serif;,使用各操作系统自带的优秀中文字体,零延迟、零成本、零隐私风险。
我改了主题functions.php,主题更新就丢了怎么办?
强烈建议创建子主题(child theme)。在wp-content/themes下新建twentyfifteen-child目录,里面放style.css(声明Template: twentyfifteen)和functions.php,所有修改都写到子主题里,主题升级父主题不会影响你的代码。这是WordPress官方推荐做法。
除了Google Fonts,还有哪些Google资源会拖慢国内访问?
常见的还有Google Analytics(gtag.js)、Google Tag Manager、reCAPTCHA、Google Maps、Google AdSense、Gravatar头像(secure.gravatar.com)等。处理思路类似:要么dequeue,要么用国内可访问的替代品(51la替代GA、腾讯地图替代Google Maps、cravatar.cn替代gravatar)。reCAPTCHA可以换成腾讯防水墙或极验。
我用的不是Twenty Fifteen,是其他主题,怎么找到字体的handle名?
两种方法。第一种,直接在主题目录里全文搜索wp_enqueue_style和googleapis,找到注册的代码就能看到handle名。第二种,用Query Monitor插件,它会列出页面上所有入队的样式表和它们的handle,一目了然,是WordPress性能调优必备工具。还有第三种"扫描式"做法,前面给过代码——遍历$wp_styles->registered过滤含googleapis的全部dequeue。
装了OMGF之后还需要单独写dequeue代码吗?
不需要。OMGF会自动接管所有Google Fonts的入队请求,把它们重写为本地路径,原本的dequeue逻辑反而可能和OMGF冲突。同一站点只用一种方案,要么纯插件,要么纯代码。
Twenty Fifteen之外,Twenty Twenty-Three / Twenty Twenty-Four这些新主题还有这个问题吗?
新主题大多已经把字体本地化了(Inter、System UI Stack或本地引入的字体),不再走Google Fonts CDN。但有些主题作者会在block patterns或Theme.json里通过fontFamilies.fontFace.src引入Google Fonts,仍然需要排查。Twenty Twenty-Four的实测结果是默认不走Google Fonts,但如果你切换了某些Block Pattern,可能间接引入。
插件大量装会不会让站点变慢?OMGF对总加载时间的影响是多少?
OMGF这种小插件本身的PHP开销在5到10毫秒级别,跟它能省下来的字体加载时间(10秒以上)比微不足道。我实测在中等配置VPS上,加装OMGF后单次PHP执行时间增加约8毫秒,OPcache命中后降到3毫秒以内,完全可接受。
有没有完全无侵入的服务器层方案?
有。可以在Nginx层面做反向代理或重写规则,把fonts.googleapis.com的请求转发到本地或国内镜像。但这种方案对运维要求高,并且和WordPress解耦带来调试不便,我个人不推荐普通站长尝试,除非你有完整的运维团队。代码层方案已经够用且可控。