新站 WordPress 上线必须做的几件事,不然以后就后悔了!(含备份回滚)

一个 WordPress 新站从"装好能用"到"搜索引擎愿意收录",中间隔着一堆没人告诉你、但漏一件就出事的事。

这篇是我自己踩过一遍之后整理的上线清单。全部在宝塔面板 + nginx + PHP 8.2 + MySQL 5.6 的国内云主机上实测过,每条都写了为什么做和不做会怎样。最后一部分是备份和回滚——这部分我建议你哪怕别的都跳过,也要看完。

WordPress 新站上线必做事项总览示意图
上线清单的七个环节:备份、伪静态、站点地图、速度、安全、结构、内容

顺序错了,做了也白做

清单条目本身不稀奇,网上到处都是。真正的问题是顺序:

① 备份(动手之前)
② 伪静态 / 固定链接(所有 URL 的地基)
③ 站点地图 + robots
④ 速度优化(资源、缓存、图片)
⑤ 安全加固(权限、入口、备份脚本)
⑥ 结构优化(面包屑、低质页处理)
⑦ 内容策略(这才是决定收录的)

为什么备份排第一?因为第②步一旦做错,全站 404。没备份你就只能重装。


一、动手之前:把"能退回去"这件事做掉

这一步九成新手跳过。跳过的人里,有一部分会在两小时后重新建站。

要备份三样东西:

对象 说明 常见遗漏
数据库 文章、页面、设置、用户全在这 只导出 .sql 不验证内容
wp-content 主题、插件、上传的图片 忘了 uploads 目录(图片全丢)
配置文件 wp-config.php、.htaccess、nginx 规则 改完没留原文件副本

命令行的做法(SSH 环境下最稳):

# 数据库(MySQL 5.6 会报 PROCESS privilege 警告,属正常,不影响数据完整性)
mysqldump -u 用户名 -p --default-character-set=utf8mb4 \
  --add-drop-table --single-transaction 数据库名 > db.sql

# 站点文件(wp-content 体积最大,通常几 MB 到几百 MB)
tar -czf files.tar.gz -C /www/wwwroot/你的站点目录 \
  wp-content wp-config.php .htaccess

本地下载一份,别只留在服务器上。 服务器磁盘挂了、误删了、被入侵了,留在同一个盘上的备份没有意义。

verification 也很简单:

grep -c "CREATE TABLE" db.sql        # 应等于 information_schema 里的表数量
tar -tzf files.tar.gz | head -20      # 能看到 wp-content/ 开头就对了
WordPress 数据库与文件备份及回滚流程示意图
数据库与文件同步备份,出问题时按同一路径回滚

一个反直觉的点:mysqldump 在 MySQL 5.6 上几乎必定输出
Warning: Using a password on the command line interface can be insecure 和
PROCESS privilege ... tablespaces 这两条警告。
它们不是错误,导出文件是完整的。别被吓到去反复重来。


二、nginx 伪静态:不补这一条,全站 404

国内主机大多用宝塔面板。宝塔建站时会生成一个"伪静态"配置文件,但新站的这个文件经常是空的。

后果很直接:WordPress 的"固定链接"只能选带 index.php 的那种,也就是:

https://example.com/index.php/2026/09/28/post-name/

这种 URL 对搜索引擎不友好(层级混乱、index.php 是噪音),而且一旦你手动改成漂亮的静态链接,全站立刻 404——因为 nginx 不知道该把 /post-name/ 交给谁处理。

修法是往伪静态文件里加这一句:

location / {
    try_files $uri $uri/ /index.php?$args;
}

宝塔的伪静态文件路径一般是:

/www/server/panel/vhost/rewrite/你的域名.conf

(注意:文件名就是完整域名,带点。)

第二步的坑:改完固定链接还是要 404

即使 try_files 加上了,如果你是通过直接改数据库里的 permalink_structure 来设置固定链接,新链接同样会 404。

原因:WordPress 把 URL 重写规则缓存在数据库的 wp_options → rewrite_rules 里。你改了 permalink_structure,但缓存的 rewrite_rules 还是旧的。

必须刷新重写规则:

# 有 wp-cli 的话
wp rewrite flush --hard

# 没有的话,写一个临时 php 文件访问一次,然后删掉

别忘了删掉那个临时文件。 留一个能刷新重写规则的 php 在网站根目录,是安全隐患。

推荐直接用的固定链接格式:

/%postname%.html

理由:中文站点用 .html 后缀在国内搜索引擎里识别度高、看起来像静态页,且不暴露日期(发布日期一改就换 URL 的事故可以避免)。


三、站点地图与 robots.txt

百度、搜狗、必应都靠 sitemap 发现新内容。WordPress 自带一个 /wp-sitemap.xml,但它把附件页、作者页、标签页全都塞进去了——这些恰恰是低质页面。所以要么改装插件(Yoast / Rank Math),要么自己生成一份干净的。

自己生成的好处:零插件、加载快、可控。

思路是写一个读取数据库的 PHP,只输出三类 URL:

首页(priority 1.0)
文章与页面(0.9 / 0.8)
有内容的分类(0.6)

并且加一层文件缓存,1 小时才重新查库一次,避免每次请求都跑 SQL:

$xml_file = __DIR__ . '/sitemap.xml';
if (is_readable($xml_file) && (time() - filemtime($xml_file)) < 3600) {
    header('Content-Type: application/xml; charset=UTF-8');
    readfile($xml_file);
    exit;
}

然后用 nginx 把 /sitemap.xml 指过去:

location = /sitemap.xml {
    try_files $uri /sitemap.php?$args;
}

robots.txt 要单独对百度说明一遍。 很多站长只写一个 User-agent: *,但百度的爬虫对独立段落响应更好:

User-agent: *
Allow: /
Disallow: /wp-admin/
Allow: /wp-admin/admin-ajax.php
Disallow: /wp-includes/
Disallow: /*?s=
Disallow: /search
Disallow: /attachment/

User-agent: Baiduspider
Allow: /
Disallow: /wp-admin/
Disallow: /*?s=

Sitemap: https://你的域名/sitemap.xml

注意最后一行——sitemap 地址写进 robots.txt,百度会主动来抓。


四、速度优化:国内主机最容易忽略的三件事

1. 把 Google Fonts 干掉

很多免费主题(包括 GeneratePress 的某些配置)会在 <head> 里加载 Google Fonts。国内访问 fonts.googleapis.com 直接超时,浏览器要等它超时才继续渲染——首屏白屏 3 秒起步。

在 functions.php 或自己写的小插件里屏蔽:

add_action('wp_enqueue_scripts', function () {
    global $wp_styles;
    if (empty($wp_styles->registered)) return;
    foreach ($wp_styles->registered as $handle => $obj) {
        $src = isset($obj->src) ? $obj->src : '';
        if (strpos($src, 'fonts.googleapis.com') !== false
            || strpos($src, 'fonts.gstatic.com') !== false) {
            wp_dequeue_style($handle);
            unset($wp_styles->registered[$handle]);
        }
    }
}, 100);

替代方案是用系统字体栈(-apple-system, "PingFang SC", "Microsoft YaHei"),中文站点本来也不需要衬线英文字体。

2. 关掉 emoji、oEmbed、静态资源版本号

WordPress 默认会为 emoji 加载一段 JS 和一个外部图片请求,为 oEmbed 输出一堆 <link>,给每个 css/js 加 ?ver=x.y.z。

  • emoji:中文博客基本用不到,纯浪费
  • oEmbed:不做视频嵌入就完全没用
  • ?ver=:让代理层/CDN 无法缓存,每次都回源

前两个用 remove_action 摘掉,第三个用一个 filter 过滤掉 ver 参数,大概能省下 3-5 个请求。

3. 图片:上传前先压

这条最容易被忽略,也最影响体验。一张手机拍的截图 2-3MB,一篇文章放 3 张就是 8MB。自己刚做完速度优化,转头往文章里塞大图,属于自己打自己脸。

标准做法:宽度压到 1200px、格式转 WebP、单图控制在 150KB 以内。

WebP 相比 PNG 在这种"扁平色块 + 线条"的示意图上压缩率极高。实测三张 1200px 的流程图:

原图 WebP 后 压缩率
826 KB 31 KB 96%
1457 KB 32 KB 98%
1527 KB 26 KB 98%

(用 Python 的 Pillow 批量处理,十几行代码,比装一个图片压缩插件更干净。)

from PIL import Image
im = Image.open(src).convert("RGB")
if im.width > 1200:
    im = im.resize((1200, int(im.height * 1200 / im.width)), Image.LANCZOS)
im.save(dst, "WEBP", quality=82, method=6)

五、安全加固:权限、入口、自动备份

权限归位

find /www/wwwroot/你的站点 -type d -exec chmod 755 {} \;
find /www/wwwroot/你的站点 -type f -exec chmod 644 {} \;
chmod 600 /www/wwwroot/你的站点/wp-config.php

wp-config.php 里是数据库明文密码,权限必须是 600(只有属主可读写)。默认 644 意味着服务器上任何用户都能读。

wp-config.php 里加这四行

define('DISALLOW_FILE_EDIT', true);   // 禁止后台在线编辑主题/插件源码(被入侵后最常被利用)
define('WP_POST_REVISIONS', 5);       // 限制修订版本,否则数据库半年就膨胀到几百 MB
define('AUTOSAVE_INTERVAL', 120);     // 自动保存改 120 秒,减少写入
define('EMPTY_TRASH_DAYS', 7);        // 回收站 7 天清理

DISALLOW_FILE_EDIT 特别重要:留着一个能在后台改 PHP 的入口,等于给入侵者留了后门。

nginx 层拦三样东西

# 上传目录禁止执行 PHP(否则传个伪装成图片的马上去就能跑)
location ~* /(?:uploads|files)/.*\.php$ {
    deny all;
}

# 关掉 xmlrpc.php(暴力破解和 pingback 放大攻击的主要入口)
location = /xmlrpc.php {
    deny all;
}

# 禁止访问隐藏文件
# ⚠️ 必须排除 .well-known,否则 Let's Encrypt 证书续签会失败
location ~ /\.(?!well-known) {
    deny all;
}

最后那条的 (?!well-known) 是我自己踩过的坑,下面单独说。

坑:location ~ /\. 会让 SSL 证书续签失败

我一开始写的是:

location ~ /\. {
    deny all;
}

想法很朴素:.git、.env、.htaccess 这些敏感文件不该被访问。

问题在于 nginx 的 location 匹配规则:正则 location 按书写顺序匹配,先命中先执行。我的规则写在宝塔自动生成的这段之前:

location ~ \.well-known {
    allow all;
}

结果 /well-known/acme-challenge/xxxx 先被我的规则命中,返回 403。Let's Encrypt 验证服务器拿不到那个 token 文件,证书到期后续签直接失败,网站变成不受信任。

这个坑的可怕之处在于:它不会立刻报错。你做优化的时候一切正常,三个月后证书到期才发现,那时候你早就忘了自己改过什么。

修法就是加一个负向先行断言,把 .well-known 排除掉:

location ~ /\.(?!well-known) {
    deny all;
}

改完记得验证一下:

# 应该返回放行后的结果(404 也算正常,说明没被拦)
curl -sI https://你的域名/.well-known/acme-challenge/test | head -1
# .git 之类仍然应该被拦
curl -sI https://你的域名/.git/config | head -1   # 期望 403

改 nginx 前一定要备份原配置,并且 nginx -t 通过才 reload。 一个可靠的流程:

nginx 请求匹配与规则校验流程示意图
改 nginx 规则的标准流程:备份 → 写入 → 语法校验 → 平滑重载,失败即回滚

写成一个 shell 脚本,出错自动回滚。手工改配置然后 reload 失败,重灾区就是"以为改好了,其实 nginx 已经起不来"。

下面是这个脚本的核心逻辑,关键是校验不通过就立刻还原,而不是硬 reload:

#!/bin/bash
set -u
CONF="/www/server/panel/vhost/rewrite/你的域名.conf"
BAK="${CONF}.bak-$(date +%Y%m%d%H%M%S)"

# 1. 备份(原文件为空时也要处理)
if [ -s "$CONF" ]; then
    cp -a "$CONF" "$BAK"
    echo "原规则已备份 → $BAK"
else
    echo "原规则为空,无需备份"
fi

# 2. 写入新规则
cat > "$CONF" <<'WPRULES'
location / {
    try_files $uri $uri/ /index.php?$args;
}
location = /sitemap.xml {
    try_files $uri /sitemap.php?$args;
}
location ~* /(?:uploads|files)/.*\.php$ { deny all; }
location = /xmlrpc.php { deny all; }
# 注意 (?!well-known),见上文
location ~ /\.(?!well-known) { deny all; }
WPRULES

# 3. 语法校验:不通过直接回滚并退出
if nginx -t >/tmp/nginx_test 2>&1; then
    echo "nginx -t 通过"
else
    echo "nginx -t 失败,回滚"
    cat /tmp/nginx_test
    if [ -f "$BAK" ]; then cp -a "$BAK" "$CONF"; else : > "$CONF"; fi
    exit 1
fi

# 4. 平滑重载
nginx -s reload

这个脚本的每一行都是被坑出来的:第 1 步的 -s 判断(避免对空文件 cp 报错)、第 3 步的失败回滚、以及 .well-known 的排除。


六、结构化数据与站点结构

面包屑 + BreadcrumbList

面包屑不只是给用户看导航,更重要的是给搜索引擎站点层级信息。配合 JSON-LD 输出 BreadcrumbList,百度能知道"这篇文章属于哪个分类、分类属于哪个站",对提升收录质量有实际帮助。

// 输出结构化数据(简化示意)
$json = [
    '@context' => 'https://schema.org',
    '@type'    => 'BreadcrumbList',
    'itemListElement' => [
        ['@type' => 'ListItem', 'position' => 1, 'name' => '首页', 'item' => home_url('/')],
        ['@type' => 'ListItem', 'position' => 2, 'name' => $cat_name, 'item' => $cat_url],
        ['@type' => 'ListItem', 'position' => 3, 'name' => get_the_title()],
    ],
];

文章页还要输出 Article 类型的 JSON-LD(标题、发布时间、修改时间、作者、封面图)。这两块加起来不到 50 行 PHP,比装一个 SEO 插件轻得多。

处理"低质页面"

这一节是针对一个具体问题写的:用 AI 批量产内容的站点特别容易被判垃圾站。

搜索引擎判断低质站的信号里,有几个和内容质量无关,纯粹是结构性问题:

信号 为什么算低质 处理方式
图片附件页 只有一张图 + 一行字,典型空壳页 is_attachment() → 301 跳回所属文章
标签页 内容与分类页/首页高度重复 noindex, follow
空分类页 0 篇文章,纯入口页 noindex, follow
作者页 单作者博客的作者页 ≈ 首页 noindex, follow
分页第 2 页起 <title> 与第 1 页完全相同 标题补「(第 2 页)」
归档页输出全文 与文章页内容 100% 重复 主题设置里改成只输出摘要

noindex, follow 是关键:不索引这个页面,但蜘蛛仍然可以顺着页面上的链接抓到文章。如果直接 nofollow 或者屏蔽抓取,反而会切断内链。

对应的几段代码:

// 1. 附件页 301 归集到所属文章
add_action('template_redirect', function () {
    if (!is_attachment()) return;
    $post = get_queried_object();
    $url  = home_url('/');
    if ($post && $post->post_parent) {
        $url = get_permalink($post->post_parent) ?: $url;
    }
    wp_safe_redirect($url, 301);
    exit;
}, 1);

// 2. 低质聚合页 noindex
add_action('wp_head', function () {
    $noindex = false;
    if (is_tag() || is_author()) {
        $noindex = true;
    } elseif (is_category()) {
        $cat = get_queried_object();
        if ($cat && (int) $cat->count === 0) $noindex = true;
    }
    if ($noindex) echo '<meta name="robots" content="noindex,follow" />' . "\n";
}, 5);

// 3. 分页标题去重
add_filter('document_title_parts', function ($title) {
    if (is_paged()) {
        $paged = (int) get_query_var('paged');
        if ($paged > 1 && isset($title['title'])) {
            $title['title'] .= sprintf('(第 %d 页)', $paged);
        }
    }
    return $title;
});

还有一条在主题设置里,不在代码里:归档页只输出摘要,不要输出全文。

用 GeneratePress 的话,后台「外观 → 自定义 → 布局」把归档页的内容改成摘要(Excerpt)。这个选项决定了首页、分类页是输出全文还是摘要——输出全文的情况下,你的首页和每篇文章页内容完全重复,这是搜索引擎判定重复内容最直接的依据。

RSS 同理:设置 → 阅读 → 摘要(而不是全文)。否则整站内容会被采集站一次性抓走。


七、备份与回滚:真正保命的部分

前面六节都是在"做对"。这一节是在"做错之后还能活"。

回滚能力决定你敢不敢动手

很多优化不敢做,原因就一个:怕搞坏。

  • 不敢改 nginx,怕站点起不来
  • 不敢改固定链接,怕全站 404
  • 不敢动主题配置,怕页面乱掉

一旦你知道"随时能退回去",上面这些动作全变成低成本操作。清单里那些条目为什么敢一条条试?因为背后有回滚通道兜着。

所以最该先建立的不是"优化清单",是回滚通道。

三档回滚

档位 覆盖场景 恢复耗时
单文件回滚 改坏了某个配置文件 秒级(直接 cp 回来)
全站回滚 数据库或文件被搞坏 分钟级(导入 sql + 解压)
异地恢复 服务器磁盘故障 / 被入侵 小时级(换机器重建)

第一档最常用,做法很简单:每次改配置前先 cp 原文件 原文件.bak-时间戳。

STAMP=$(date +%Y%m%d%H%M%S)
cp /www/server/panel/vhost/rewrite/你的域名.conf \
   /www/server/panel/vhost/rewrite/你的域名.conf.bak-$STAMP

出问题时:

cp /www/server/panel/vhost/rewrite/你的域名.conf.bak-20260928173012 \
   /www/server/panel/vhost/rewrite/你的域名.conf
nginx -t && nginx -s reload

注意时间戳——留一堆 .bak 而不知道哪个是哪次改的,等于没备份。

全站回滚的实际步骤

# 1. 先停掉写入,避免"边导入边有人访问"造成数据不一致
#    (宝塔面板可一键停 PHP;或临时把站点目录改名也行,宁可 502 也别写脏数据)
mv /www/wwwroot/你的站点 /www/wwwroot/你的站点.broken

# 2. 解压文件 + 归属权修正(这一步最容易漏)
tar -xzf files.tar.gz -C /www/wwwroot/你的站点
chown -R www:www /www/wwwroot/你的站点

# 3. 导入数据库
mysql -u 用户名 -p --default-character-set=utf8mb4 数据库名 < db.sql

# 4. 恢复 nginx 规则并校验
nginx -t && nginx -s reload

第 2 步的 chown 是重灾区。 用 root 解压出来的文件属主是 root,PHP-FPM 以 www 用户运行,读不到文件 → 全站 500。这个问题现象是"文件明明都在,但网站就是打不开",很多人在这里卡很久。

把备份自动化,并且验证它真的在跑

手工备份一定会忘。配一个 cron:

#!/bin/bash
# /usr/local/bin/wp_site_backup.sh
set -e
STAMP=$(date +%F)
DIR=/root/wp_backups
mkdir -p $DIR

mysqldump -u 用户名 -p密码 --default-character-set=utf8mb4 \
  --single-transaction 数据库名 > $DIR/db-$STAMP.sql
tar -czf $DIR/files-$STAMP.tar.gz -C /www/wwwroot/你的站点 \
  wp-content wp-config.php 2>/dev/null || true
gzip -f $DIR/db-$STAMP.sql
find $DIR -type f -mtime +7 -delete       # 只留 7 天
echo "$(date) backup done" >> /var/log/wp_backup.log
0 3 * * * /usr/local/bin/wp_site_backup.sh

然后一定要验证:

tail /var/log/wp_backup.log          # 看有没有今天的记录
ls -lh /root/wp_backups/             # 看文件大小是否合理(几 KB 说明导出失败)

没验证过的备份等于没有备份。定时任务是"配置了"和"在跑"两件事,
而"在跑"和"备份内容可用"又是两件事。三层都要确认。

最后一句:异地

服务器磁盘故障、被入侵删库、误操作 rm -rf——这三种情况下,存在同一台服务器上的备份会一起没。

每周手工下载一次到本地,或者用对象存储(腾讯云 COS / 阿里云 OSS)配一个同步任务。成本几毛钱,换的是"最坏情况下内容资产还在"。


附:完整清单(可直接当 checklist 用)

动手前

  • ☐ 数据库导出,验证 CREATE TABLE 数量正确
  • ☐ wp-content 打包(含 uploads)
  • ☐ wp-config.php / .htaccess / nginx 规则单独留副本
  • ☐ 下载一份到本地或对象存储

URL 与收录

  • ☐ 伪静态文件补 try_files $uri $uri/ /index.php?$args
  • ☐ 固定链接设为 /%postname%.html
  • ☐ 刷新重写规则(wp rewrite flush --hard),删掉临时 php
  • ☐ sitemap 部署并验证输出 <urlset
  • ☐ robots.txt 写入,含 Sitemap 地址
  • ☐ 百度站长平台提交 sitemap + API 推送

速度

  • ☐ 屏蔽 Google Fonts
  • ☐ 关 emoji / oEmbed / ?ver=
  • ☐ gzip 开启(宝塔一般已默认开)
  • ☐ 静态资源缓存 30 天
  • ☐ 图片压到 1200px + WebP + 150KB 内
  • ☐ 归档页输出摘要,RSS 输出摘要

安全

  • ☐ 目录 755 / 文件 644 / wp-config.php 600
  • ☐ DISALLOW_FILE_EDIT 等四个常量
  • ☐ uploads 禁执行 PHP
  • ☐ xmlrpc.php 拦截
  • ☐ 隐藏文件拦截 (记得排除 .well-known)
  • ☐ 每日备份 cron + 验证日志
  • ☐ 后台地址改名、强密码、登录失败限制

结构

  • ☐ 面包屑 HTML + BreadcrumbList
  • ☐ Article JSON-LD
  • ☐ 附件页 301 归集
  • ☐ 标签页 / 空分类页 / 作者页 noindex,follow
  • ☐ 分页 title 去重

内容(决定收录,比上面所有项都重要)

  • ☐ 先积累 8-15 篇原创,再提交收录
  • ☐ 每天 1-2 篇稳定节奏,不要一天发 20 篇然后停一周
  • ☐ 分类 3-5 个,标签能不用就不用
  • ☐ 每篇有真实经验、具体命令、可验证的数据

真正会出事的只有四条

上面这张清单,条目看着多,真出事的就四个:没备份就改配置、nginx 规则挡住 .well-known、uploads 能执行 PHP、归档页输出全文。其余的属于加分项,做了更好,不做也不至于翻车。

还有一条不在清单里,但它决定了上面所有条目的价值:内容得有人味。

第六条那些结构优化,解决的是"结构性低质信号"。可如果内容本身是批量生成的、没有实测数据、没有具体命令、没有任何个人经验,结构改得再干净也只是"包装整齐的批量内容"。搜索引擎识别这个的能力,这两年提升得很快。

我的判断标准是:一篇能被搜索引擎当回事的文章,至少得有一样东西是别人抄不走的——你自己的错误、你自己的数据、你自己的环境细节。这篇里那些"踩过的坑",就是这一类东西。


本站为个人技术记录,内容均为原创实操总结,转载请注明出处。

发表评论