本文约 3,831 字,预计阅读 10 分钟。文中命令与配置均经过实测,可直接参考执行。
引言:勾上”优化”之后,轮播图不动了
Autoptimize 是免费插件里做前端文件优化最成熟的一款,能压缩和合并 CSS/JS、内联关键 CSS、延迟加载图片、把小图转成 data URI。它通常和页面缓存插件搭配使用——缓存插件负责”不启动 PHP”,Autoptimize 负责”减少和缩小请求”。
但它的失败案例高度雷同:启用之后前台样式错乱、滑块不动、菜单下拉失效。原因几乎总是同一类:合并改变了文件的加载顺序,或者把某个依赖同步执行的内联脚本延后/移动了。Autoptimize 默认行为很激进(把内联脚本也合并移动),所以要稳定使用,必须理解它的排除机制。
原理分析:exclude、dontmove 与 defer 的区别
Autoptimize 的 JS 处理逻辑大致是:收集页面上所有通过 wp_enqueue_script 注册的外链脚本和内联脚本 → 合并成一个(或几个)文件 → 放到 <head> 或页脚。在这个过程中有三个控制维度:
| 控制项 | 对应行为 | 典型用途 |
|---|---|---|
| Exclude(排除) | 完全不处理这个脚本/样式,原样留在页面上 | 第三方统计、广告、必须保持原 URL 的脚本 |
| Dontmove(不移动) | 参与压缩但不改变在页面中的位置 | 依赖执行顺序的内联脚本 |
| Aggregate inline(聚合内联) | 是否把内联脚本并入合并文件 | 默认关闭更安全 |
| Defer / Async | 异步化,把脚本延后执行 | 对非首屏脚本有效,风险较高 |
关键区别在于 Exclude 和 Dontmove:Exclude 是”别碰它”,Dontmove 是”可以压,但别挪位置”。内联脚本失效时,正确做法通常是 Dontmove 而不是 Exclude——因为它仍需要被压缩,只是不能改变它相对于其他脚本的执行时序。
对应的过滤器命名很规律:
autoptimize_filter_js_exclude/autoptimize_filter_css_exclude:排除列表;autoptimize_filter_js_dontmove/autoptimize_filter_css_dontmove:不移动列表;autoptimize_filter_noptimize:整个页面关闭优化;autoptimize_filter_js_defer:控制 defer 行为。
这些过滤器都是 Autoptimize 官方 API 的一部分,写在子主题或功能插件里比在后台文本框里填更持久——后台的设置会在插件重置时丢失。
保姆级实操
第一步:基础设置
后台 设置 → Autoptimize:
- Optimize HTML Code:开;
- Optimize JavaScript Code:开;
- Optimize CSS Code:开;
- Aggregate JS-files:开(HTTP/2 下仍有一定收益,因为能减少内联与外部文件的往返);
- Aggregate CSS-files:开;
- Also aggregate inline JS:先关,稳定后再试;
- Add try-catch wrapping:关(会掩盖真实错误)。
第二步:用过滤器写排除清单
<?php
// 排除必须保持原样的脚本:统计、广告、支付
add_filter( 'autoptimize_filter_js_exclude', function ( $exclude ) {
return $exclude . ', googletagmanager, gtag, adsbygoogle, stripe, jquery.min.js';
} );
// 排除构建器与主题的核心样式,避免合并后顺序错乱
add_filter( 'autoptimize_filter_css_exclude', function ( $exclude ) {
return $exclude . ', elementor, admin-bar.min.css, dashicons.min.css';
} );
// 这些脚本可以被压缩,但不能改变位置(依赖执行顺序)
add_filter( 'autoptimize_filter_js_dontmove', function ( $dontmove ) {
return $dontmove . ', recaptcha, wp-emoji-release.min.js, swiper';
} );
// 购物车、结算页完全不优化
add_filter( 'autoptimize_filter_noptimize', function ( $noptimize ) {
if ( function_exists( 'is_checkout' ) && ( is_checkout() || is_cart() ) ) {
return true;
}
return $noptimize;
} );
第三步:确认缓存目录可写且定期清理
# Autoptimize 的合并产物目录
ls -lh wp-content/cache/autoptimize/ | head
du -sh wp-content/cache/autoptimize/
# 改了设置后必须清空
rm -rf wp-content/cache/autoptimize/*
# 确认目录属主与 Web 服务一致
stat -c '%U %G' wp-content/cache/autoptimize/
第四步:逐页验证而不是只看首页
for u in / /about /product-demo /contact; do
printf "%-18s " "$u"
code=$(curl -o /dev/null -s -w '%{http_code}' "https://mimangfei.com$u")
njs=$(curl -s "https://mimangfei.com$u" | grep -c '<script')
echo "HTTP=$code script标签=$njs"
done
对比优化前后的 <script> 数量,再去浏览器 Console 面板看有没有 undefined is not a function 这类报错——这类报错基本都是内联脚本被移动后找不到依赖。
第五步:与缓存插件的分工
Autoptimize 只做文件优化,不做页面缓存。它必须和一个缓存插件(WP Rocket、LiteSpeed Cache、WP Super Cache 等)搭配。两者都开时,注意不要在两个插件里同时开启”延迟 JS”或”合并 CSS”,重复优化会导致文件被处理两次。
常见踩坑
- 内联脚本被移动后失效。典型症状是页面上有
$ is not defined或某个全局变量找不到。用 dontmove 而不是 exclude 修。 - 合并破坏了加载顺序。Elementor、Divi 这类构建器会按组件加载多份 CSS,合并后优先级变化,样式被覆盖。排除构建器的主 CSS。
- 案例:某站点开启 Autoptimize 后,联系表单的提交按钮点了没反应,Console 报
wpcf7 is not defined。原因是 Contact Form 7 的内联初始化脚本被聚合并移到了合并文件里,而 jQuery 已经被排除在外,执行时 jQuery 尚未就绪。修复是把wpcf7加入autoptimize_filter_js_dontmove,让初始化脚本留在原位。 - 缓存目录权限不对。合并文件写不进去,前台可能直接报 500 或加载空白 CSS。
- 改了设置没清缓存目录。前台仍在用旧的合并文件,误以为设置无效。
- 同时开了 CDN 但 URL 没改写。合并文件路径仍是本地,CDN 加速不到。
- 把
jquery也排除了结果全站脚本报错。jQuery 应尽量参与合并而不是排除,除非确认有冲突。 - data URI 把大图内联进了 CSS。开启 “Generate data: URIs for images” 时要限制尺寸,否则 CSS 文件反而变大。
总结
Autoptimize 的稳妥用法是:先只开 HTML/CSS/JS 压缩与合并,内联聚合和 defer 先关;然后用过滤器写一份排除与 dontmove 清单,把统计、广告、支付、构建器样式全部排除或保留原位;最后逐页验证并清空缓存目录。判断标准只有两条:浏览器 Console 无报错,以及所有交互元素(表单、滑块、菜单、加购)都能正常工作。做到这两条,合并压缩带来的请求数下降才是真实收益。
前端优化之外,按需卸载无用资源同样重要,见 Asset CleanUp 与 Perfmatters 按页面卸载资源;缓存层建议配合 WP Rocket 配置全解析 一起用。
