织梦手机版静态HTML生成:5步arctype切表法实战

运维八年织梦经验,手把手讲清arctype切表生成手机版静态HTML的5步流程,附87栏目和121800文档站实测耗时、Nginx路由配合、Bash一键脚本和钉钉告警,从原理到自动化一次讲透。

张文保 更新 34 分钟阅读 3,909 阅读
本文目录
  1. 为什么织梦默认手机端不能生成静态
  2. DedeCMS 5.7 与 5.8 在生成逻辑上的差异
  3. 核心思路:用SQL给arctype做“双胞胎”
  4. 复制一份arctype作为手机端模板表
  5. 把现网生效的arctype切换为手机端配置
  6. 到栏目管理里把所有栏目的目录和模板改成手机版
  7. 跑生成,输出手机端列表页和文档页
  8. 把arctype切回PC配置
  9. 切回后的烟雾测试清单
  10. 配套的Nginx路由策略
  11. 与 HTTPS、HSTS 的配合
  12. URL 二级目录方案 vs 自适应 RWD 方案
  13. 性能基线与三种规模的真实数据
  14. 一键 Bash 脚本与定时任务封装
  15. 升级与迁移注意事项
  16. 常见错误码与排查
  17. 常见问题解答
  18. 每次发新文章,都要重新切表跑一遍生成吗?
  19. 切表过程中如果断电或者SQL执行一半失败怎么办?
  20. 还有更优雅的方案吗?比如不切表?
  21. 生成出来的HTML文件占用空间会不会很大?
  22. 百度移动端和 PC 端会不会因为内容相同被判重复?
  23. 切表期间发布的新文章会丢吗?
  24. 多语言站点(中英双语)怎么处理?
  25. 能不能不依赖后台“生成”按钮,直接用 PHP 命令行生成?
  26. 写在最后

我是保哥,运维织梦DedeCMS站点已经有八年时间。这篇文章想跟大家分享一个我用了很多年、并且一直稳定有效的方法:通过切换arctype数据表,让织梦的手机版(移动端)也能生成静态HTML文件。这个需求看起来冷门,但只要你做过移动端SEO,就一定会遇到——动态PHP页面在移动端百度搜索里收录速度比静态页面慢一截,特别是新站。下面把完整步骤、底层原理、上线流程和踩过的坑全部写出来。

为什么织梦默认手机端不能生成静态

先说结论:织梦的“生成”功能是按arctype表里登记的目录和模板路径来工作的,而arctype默认只存了PC端的目录和模板路径。手机端虽然有自己的模板(一般在/templets/default_m/里),但它的栏目目录信息从来没有被写进arctype,所以后台“生成HTML”按钮根本看不到手机端栏目。

这是为什么你点遍后台所有“生成”按钮,移动端永远是PHP动态访问的根本原因。要让它生成静态HTML,思路有两条:

  1. 改源码:让织梦的生成器同时识别PC模板和手机模板。这种改动量大、容易和后续升级冲突。
  2. 临时切表:备份一份arctype,临时把里面的目录和模板改成手机端的,跑一次生成,再切回来。代价小,可重复,是我个人最推荐的做法。

这篇我们重点讲第二种。

DedeCMS 5.7 与 5.8 在生成逻辑上的差异

在动手之前你必须先确认一件事:你的织梦版本。我维护过的客户站里,5.7 SP2 和 5.8 RC1 在 arctype 表上有两处差别——5.8 给 arctype 加了 cross_tid(跨站点引用)和 sitepath(多站点根路径)两列,这两列对单站点用户没影响,但如果你机械地照搬 5.7 时代的切表脚本到 5.8,CREATE TABLE LIKE 出来的备份表会带上这两列的默认空值,跑生成时部分自定义模板里如果 if 判断了 cross_tid 会走入死分支。我在客户站上踩过这个坑,最后的修复是把切表 SQL 改成显式列出列名,而不是 SELECT *。

另一个差别:5.8 之后的 arc.partview.class.php 在 SetTypelink 方法里会按 typeid 拉一次 arctype,如果 RENAME 中途有写请求,会触发 PHP fatal。所以切表必须在低峰期、并且把后台对运营临时关闭。后面第二步会再讲怎么用一个 IP 白名单临时锁住后台。

核心思路:用SQL给arctype做“双胞胎”

这套方法的精髓在于:让数据库同时拥有两份arctype表,一份对应PC配置,一份对应手机配置。需要生成谁的静态时,就把对应的那份表RENAME到dede_arctype这个生效名字下,跑完生成再切回来。

整个流程一共五步,下面一步一步写明白。先用一张表概括“三个状态”:

状态dede_arctypedede_arctype1dede_arctype2
初始(PC生效)PC配置
第一步后PC配置PC快照
第二步后PC快照(待改手机)PC配置(下线收纳)
第三步后手机配置PC配置(下线收纳)
第五步后(PC生效)PC配置手机配置

切表的本质就是让“生效名字”在 PC 配置和手机配置之间反复轮替。理解了这张表后,下面五步就只是 SQL 操作而已。

复制一份arctype作为手机端模板表

登录后台,进入“系统”→“SQL命令行工具”,执行下面的SQL。注意,织梦默认的表前缀是dede_,但SQL命令里要用占位符#@__,织梦会自动替换成你站点真实的前缀(这点对多站环境特别重要):

CREATE TABLE `#@__arctype2` SELECT * FROM `#@__arctype`;

执行成功后,数据库里会多出一张dede_arctype2表,结构和数据都和dede_arctype完全一致。这一步的目的是先做一份“PC配置的备份”。

稍后我们要做的事,是把dede_arctype改造成“手机配置”,等生成完静态再用dede_arctype2把PC配置还原回来。

关于索引和主键的细节:因为CREATE TABLE...SELECT不会复制原表的索引和主键,所以严格来说dede_arctype2不是一个完美的克隆。但因为我们只是把它当作中转表用,索引差异不会影响RENAME操作和数据恢复,可以放心使用。如果你担心生成期间有非常重的 reorder by id 操作,可以补一条 ALTER:

ALTER TABLE `#@__arctype2` ADD PRIMARY KEY (`id`), ADD INDEX `topid` (`topid`), ADD INDEX `sortrank` (`sortrank`);

不加这条 ALTER 的话,5 万条以内的栏目数据走全表扫描也不会有明显的体感差异——我在 87 栏目和 312 栏目两个站上对比过,差距大概在 0.4 秒以内。

把现网生效的arctype切换为手机端配置

继续在“SQL命令行工具”里执行:

ALTER TABLE #@__arctype RENAME #@__arctype1;
ALTER TABLE #@__arctype2 RENAME #@__arctype;

这两条SQL干的事:

  • 把当前生效的dede_arctype(PC配置)改名成dede_arctype1,相当于把它“下线收纳”;
  • 把第一步建好的dede_arctype2改名成dede_arctype,让它成为新的生效表。

执行完,目前数据库里有两张表:dede_arctype(即将被改成手机配置)、dede_arctype1(PC配置的快照)。

原子性提醒:这两条SQL必须一起执行,中间不能有其他人在后台发文章,否则织梦会因为找不到arctype表而报错。我一般会选择凌晨2点到4点流量低谷期操作,并且在操作前先把/dede/login.php这个后台入口在Nginx里临时改成只允许我自己的IP访问:

location ~ ^/dede/ {
    allow 1.2.3.4;
    deny all;
    fastcgi_pass unix:/tmp/php-cgi.sock;
    ...
}

这一招比改后台密码安全得多——任何运营同事即使在切表的 30 秒里点开了发文页面,都会被 Nginx 返回 403,不会真的命中 PHP 业务逻辑。生成跑完再把这段 allow/deny 删掉就行。

RENAME 原子性的真相:MySQL 的 RENAME TABLE 在单个语句里是原子的,但你写成两条语句中间是有间隙的。更严谨的写法是放在一个 RENAME 里:

RENAME TABLE `#@__arctype` TO `#@__arctype1`, `#@__arctype2` TO `#@__arctype`;

这种写法 MySQL 会在内部用一次表锁完成两次重命名,对外完全不可见中间态。我后来都改用这种写法,前面那种两条 ALTER 只是为了讲清楚两步逻辑而已。

到栏目管理里把所有栏目的目录和模板改成手机版

进入后台“核心”→“网站栏目管理”,逐个点开每个栏目,做两件事:

  1. 把“保存目录”从a/news这样的PC路径,改成m/news这样的手机端路径;
  2. 把“列表模板”“文档模板”“封面模板”从default/list_article.htm这种PC模板,改成default_m/list_article.htm这种手机端模板。

如果你的栏目数量很多(我之前一个客户站有87个栏目),手动改非常折磨。可以直接写一条SQL批量更新:

UPDATE `#@__arctype`
SET `typedir` = REPLACE(`typedir`, '/a/', '/m/'),
    `templist` = REPLACE(`templist`, 'default/', 'default_m/'),
    `temparticle` = REPLACE(`temparticle`, 'default/', 'default_m/'),
    `tempindex` = REPLACE(`tempindex`, 'default/', 'default_m/');

执行前务必先备份整张arctype,因为REPLACE是字符串替换,如果你的路径里恰好有/a/这种子串(比如某个栏目的 typedir 写成了 /article/a/2024/),可能会被误改。备份命令很简单:

CREATE TABLE `#@__arctype_safe_20260507` SELECT * FROM `#@__arctype`;

路径冲突自检 SQL:在执行 UPDATE 之前先跑下面这条查询,找出潜在被误伤的栏目:

SELECT id, typename, typedir, templist, temparticle
FROM `#@__arctype`
WHERE typedir LIKE '%/a/%' AND typedir NOT LIKE 'a/%'
   OR templist LIKE '%default/%' AND templist NOT LIKE 'default/%';

如果有返回行,说明你的栏目里有路径包含 /a/ 但不是以 a/ 开头的,REPLACE 会把它一起改坏。这种情况我会手工列出来用 WHERE id IN(...) 精确更新。

UPDATE 出错的回滚:如果发现 UPDATE 改坏了,立刻在“SQL 命令行工具”里跑:

DROP TABLE `#@__arctype`;
CREATE TABLE `#@__arctype` SELECT * FROM `#@__arctype_safe_20260507`;

这就是为什么前面强调要先建 _safe_ 备份表——它就是用来撑 1 分钟内回滚的保险。

跑生成,输出手机端列表页和文档页

回到后台“生成”菜单,按以下顺序操作:

  1. “更新栏目HTML”→ 全部更新;
  2. “更新文档HTML”→ 全部更新;
  3. “更新主页HTML”→ 把主页位置改成/m/index.html、模板改成default_m/index.htm,再点生成。

生成完毕,在服务器/m/目录下应该会出现完整的栏目目录树和静态HTML文件。这时候用手机访问任意一个栏目URL,都能看到纯静态的页面。

实测耗时基线:生成耗时取决于你的文档总量。我手头有三个长期跟踪的站,给你做个参考:

站点规模栏目数文档总数全量生成耗时磁盘占用
小站123,8002 分 14 秒92 MB
中站8734,50011 分 47 秒820 MB
大站312121,80047 分 26 秒3.1 GB

建议在生成前临时把PHP的max_execution_time调大到600秒以上,并且把 memory_limit 调到 512M。我在大站上还把 php-fpm 的 pm.max_children 临时从 50 调到 80,避免后台生成长事务把 fpm 池塞满影响前台访问。

分批生成而不是全量:如果你的文档超过 5 万篇,建议不要一次点“全部更新”,而是用“按栏目更新”分批跑,每跑完一个栏目去 /m/ 目录下用 find 抽检几个文件:

find /www/wwwroot/yoursite.com/m/news -name "*.html" -newer /tmp/.gen_start -type f | head -20
find /www/wwwroot/yoursite.com/m/news -name "*.html" -size -1k -type f | head -5

第二条命令专门找小于 1KB 的 HTML——这通常是生成超时或者模板渲染出错产生的“空壳文件”。一旦发现就要查 PHP 错误日志。

把arctype切回PC配置

生成完一定要切回去!不然下次发稿时,文章会按手机配置写入到/m/目录下,把PC站搞乱。继续在“SQL命令行工具”里执行:

RENAME TABLE `#@__arctype` TO `#@__arctype2`, `#@__arctype1` TO `#@__arctype`;

这一步的作用:

  • 把刚刚跑过手机生成的dede_arctype改名成dede_arctype2,作为“手机配置”的快照保留下来;
  • 把第二步存起来的dede_arctype1(PC配置)改回dede_arctype,让PC重新生效。

切完之后,去后台随便点一篇PC文章,确认目录路径是a/...、模板是default/...,就说明切换成功了。

下次需要重新生成手机端静态时,只要重复第二、四、五步即可,不用再建中转表。

切回后的烟雾测试清单

我每次切回 PC 配置后,会跑一遍 5 条“烟雾测试”,确认线上服务正常:

  1. 后台“发布文章”点开,列表页能正常显示所有栏目;
  2. 后台“生成”→“更新一篇文档”拿最新一篇试跑,输出到 /a/ 目录而不是 /m/;
  3. 前台首页 / 栏目页用浏览器无痕模式打开,无 PHP fatal、无空白;
  4. Nginx access.log 看最近 200 行,确认 200 比例 ≥ 99%;
  5. 用 curl 抓一个 /m/ 目录下的旧文件,确认能 200 返回,证明 Nginx try_files 没坏。

配套的Nginx路由策略

生成静态文件只是一半的工作,另一半是要让搜索引擎和真实用户访问/m/...时优先吃静态。我习惯在Nginx里加一条try_files:

location /m/ {
    try_files $uri $uri/ $uri.html /m/index.php?$args;
    expires 5m;
    add_header Cache-Control "public, max-age=300";
}

这样请求/m/news/123.html时,Nginx会先去文件系统找静态文件,找不到才落到PHP。配合短期5分钟的浏览器缓存,对百度蜘蛛和移动用户都很友好。

与 HTTPS、HSTS 的配合

站点上 HTTPS 之后,要在这条 location 里同步加 HSTS 头,避免 PC/手机端缓存的 max-age 不一致触发降级:

location /m/ {
    try_files $uri $uri/ $uri.html /m/index.php?$args;
    expires 5m;
    add_header Cache-Control "public, max-age=300" always;
    add_header Strict-Transport-Security "max-age=31536000" always;
    add_header X-Robots-Tag "index,follow" always;
}

额外加 X-Robots-Tag 是因为我曾经吃过亏——/m/ 目录被运营同事拿来放过临时活动页,他们在 robots.txt 里把 /m/ 整个 Disallow 了,结果手机版整体被百度收录降权。后来我在 Nginx 里强制吐 X-Robots-Tag: index,follow,再配合 robots.txt 只屏蔽 /m/promo/ 这类临时子目录,问题就稳定了。

URL 二级目录方案 vs 自适应 RWD 方案

有人会问:现在响应式(RWD)这么流行,为什么还要走 /m/ 二级目录的老路子?我的回答是:织梦绝大部分 5.x 模板是 2014 年前后写的,原生 RWD 模板少而且坑多,临时改造比重做手机版要费得多。如果你的站是 2018 年之后才搭起来的、模板原生支持 viewport meta,那当然走 RWD 路线更清爽。但对于做过几年的老站、有大量历史 PC 文档需要继续吃流量,二级目录方案是迁移成本最低的。下面表对比一下:

方案改造工作量移动端首屏SEO 风险适合站点
arctype 切表生成 /m/ 静态需 alternate/canonical 互指老站、海量历史文档
响应式 RWD 重写模板取决于模板新站、模板可控
纯 PHP 动态 + Memcache 缓存取决于缓存命中动态 URL 收录慢不允许写文件系统的虚拟主机

性能基线与三种规模的真实数据

给你三个真实站点的“切表+生成”实测数据,方便你估算自己的窗口:

  • 站点 A(小型博客,3800 文档):切表 SQL 耗时 0.18 秒,全量生成 2 分 14 秒,磁盘多占 92 MB。每天凌晨 3:00 跑一次,几乎不影响白天访问。
  • 站点 B(中型行业站,34500 文档):切表 SQL 耗时 0.71 秒,全量生成 11 分 47 秒,磁盘多占 820 MB。改用每天 02:30 跑增量(只对当日修改的文档生成),耗时降到 90 秒以内。
  • 站点 C(大型新闻站,121800 文档):切表 SQL 耗时 2.4 秒,全量生成 47 分 26 秒,磁盘多占 3.1 GB。这种规模只能做增量,全量改成每周日凌晨跑一次。

给你一个经验公式:全量生成耗时 ≈ 文档数 × 0.022 秒(这是在 SSD + 8 核 CPU + PHP 7.4 + 5400 转 SATA 备份盘上测的)。如果你用 PHP 8.0,把 0.022 改成 0.017 左右——主要来自 OPcache 改进和字符串处理性能。

一键 Bash 脚本与定时任务封装

我自己用 Bash 把上面五步封装成一个脚本 dedecms_m_static.sh,配合 cron 每天凌晨自动跑。骨架长这样:

#!/usr/bin/env bash
set -euo pipefail

SITE=/www/wwwroot/yoursite.com
DB_NAME=$(grep DB_NAME ${SITE}/data/common.inc.php | head -1 | sed -E "s/.*'(.*)';/\1/")
PFX=$(grep DB_PREFIX ${SITE}/data/common.inc.php | head -1 | sed -E "s/.*'(.*)';/\1/")
LOCK=/var/lock/dedecms_m_static.lock
LOG=/var/log/dedecms_m_static.log

# 单实例锁,防止上一轮没跑完时被定时任务再次触发
exec 200>${LOCK}
flock -n 200 || { echo "$(date -Iseconds) skip: another instance running" >> ${LOG}; exit 0; }

mysql_run() {
  mysql --defaults-file=/root/.my.cnf ${DB_NAME} -e "$1"
}

echo "$(date -Iseconds) === round start ===" >> ${LOG}

mysql_run "CREATE TABLE IF NOT EXISTS ${PFX}arctype2 SELECT * FROM ${PFX}arctype;"
mysql_run "RENAME TABLE ${PFX}arctype TO ${PFX}arctype1, ${PFX}arctype2 TO ${PFX}arctype;"

# 切到手机配置
mysql_run "UPDATE ${PFX}arctype SET typedir=REPLACE(typedir,'/a/','/m/'), templist=REPLACE(templist,'default/','default_m/'), temparticle=REPLACE(temparticle,'default/','default_m/'), tempindex=REPLACE(tempindex,'default/','default_m/');"

# 触发生成(curl 后台生成接口,带 cookie)
curl -s -b /root/.dede_cookie -o /dev/null "${SITE_URL}/dede/makehtml_all_action.php?dopost=make&mtype=arc"
curl -s -b /root/.dede_cookie -o /dev/null "${SITE_URL}/dede/makehtml_list_action.php?dopost=make"
curl -s -b /root/.dede_cookie -o /dev/null "${SITE_URL}/dede/makehtml_homepage.php?dopost=make"

# 切回 PC 配置
mysql_run "RENAME TABLE ${PFX}arctype TO ${PFX}arctype2, ${PFX}arctype1 TO ${PFX}arctype;"

echo "$(date -Iseconds) === round end ===" >> ${LOG}

# 异常告警:如果 / 目录下 a/index.html 在过去 10 分钟没被生成,触发钉钉告警
if [ -z "$(find ${SITE}/a/index.html -mmin -10 2>/dev/null)" ]; then
  curl -s "https://oapi.dingtalk.com/robot/send?access_token=YOUR_TOKEN" -H "Content-Type: application/json" \
    -d '{"msgtype":"text","text":{"content":"[警告] DedeCMS 手机版静态生成可能失败,请检查"}}'
fi

脚本里几个细节值得说一下:

  1. flock 单实例锁:如果上一轮跑了 47 分钟没结束,定时任务再次触发会被 flock 直接拒绝,避免两份生成进程同时改 arctype。
  2. defaults-file:把 MySQL 密码写在 /root/.my.cnf 里(chmod 600),脚本里不出现明文密码。
  3. curl 后台接口:用 cookie 文件保持登录态,避免脚本里硬编码后台账号密码。具体登录态怎么持久化,可以用一次性 curl --cookie-jar 拿到,然后只读复用。
  4. 钉钉告警兜底:脚本最后用 find -mmin -10 判断生成是否真的产出了新文件,没产出就钉钉报警——这一步比单纯依赖脚本退出码靠谱得多。

crontab 配置:

0 3 * * * /root/scripts/dedecms_m_static.sh > /dev/null 2>&1

升级与迁移注意事项

这套切表方案在以下三种场景里要特别小心:

  1. 织梦官方 patch 修改 arctype 字段:5.7 到 5.8 之间出过 23 个 patch,其中 patch-2023-08-15 给 arctype 增加了 cross_tid 列。如果你在打 patch 之前先做了 CREATE TABLE...SELECT,再打 patch 时官方 SQL 只会 ALTER 你当前的 dede_arctype(PC 配置),不会动 dede_arctype2(手机快照)——下次切手机配置时就会因为列数不一致而失败。修复办法:每次打 patch 后立即同步给 _arctype2 也 ALTER 一遍。
  2. 迁移到 ECTouch 或其他 CMS:ECTouch 不再用 arctype 表结构,迁移工具默认只读取 dede_arctype。如果你迁移时 dede_arctype 恰好处于“手机配置”状态,新站会拿到手机端的 typedir,PC 文档全部 404。迁移前一定要确认 typedir 是 a/news 这种 PC 格式。
  3. 主从复制延迟:如果你的 MySQL 是一主一从,RENAME TABLE 在主上是原子的,但从库重放时会有几百毫秒的间隙。这段时间如果有读请求打到从库,会 ER_NO_SUCH_TABLE 报错。生成期间最好把从库摘掉,或者在应用层切到“主库优先”。

常见错误码与排查

切表过程中最高频的三个 MySQL 错误码:

  • 1146 (Table doesn't exist):99% 是因为 RENAME 只跑了一半就被中断了。立刻执行 RENAME TABLE dede_arctype1 TO dede_arctype 把 PC 配置恢复,然后查 mysql.err 看为什么被中断(通常是磁盘满或者表锁超时)。
  • 1050 (Table already exists):你之前的某轮没有完整跑完,dede_arctype2 没被消化掉。要先 DROP TABLE dede_arctype2 再重新跑第一步。如果你不确定 dede_arctype2 里面是 PC 还是手机配置,先 SELECT * FROM dede_arctype2 LIMIT 1 看 typedir 字段值再决定要不要 DROP。
  • 1064 (SQL syntax error):极有可能是你直接复制了文档里的 SQL,没把 #@__ 换成实际表前缀。织梦后台“SQL 命令行工具”会自动替换,但用 mysql 命令行直接跑就不会替换,必须手工把 #@__ 改成 dede_(或者你自己的前缀)。

常见问题解答

每次发新文章,都要重新切表跑一遍生成吗?

是的。这套方案的本质是“定期手动批处理”。我的解决办法是写一个shell脚本封装这五步,配合cron每天凌晨3点自动跑一次。如果你的内容更新非常频繁(每小时新增 50+ 篇),建议改成增量生成:只对当天新增/修改的文档做生成,可以用织梦自带的 task/index_task.php 改造。具体改法是把它里面的 GetMatchType 函数替换成读取 dede_archives.senddate > UNIX_TIMESTAMP(NOW())-3600 的 archives,然后只调用 MakeArc 重生成这部分文档。

切表过程中如果断电或者SQL执行一半失败怎么办?

这就是为什么反复强调要在低峰期操作、并且每一步都先备份的原因。万一RENAME只成功了一半,最坏的情况是dede_arctype这张表暂时不存在,织梦后台所有功能会报错。这时候手动执行 RENAME TABLE dede_arctype1 TO dede_arctype 把PC配置先恢复,站点就能立刻恢复服务。我每次操作前都把这条“应急SQL”准备好放在剪贴板里。如果你跑的是脚本,前面提到的 flock 单实例锁会避免脚本被并发触发,但断电那一刻已经在执行的 SQL 还是可能出问题——MySQL 重启后会用 InnoDB redo log 把已提交的 SQL 重放完,所以丢的最多是最后一条没提交的语句。

还有更优雅的方案吗?比如不切表?

有。两种思路:一是改 include/arc.partview.class.php 让它支持双模板路径;二是用 Cron 定时 curl 全站手机端URL,让 /m/index.php 那段缓存逻辑自己生成静态(前提是已经按我之前的文章修改了缓存判断)。但这两种都需要不少代码改动,对于不熟 PHP 的站长来说,切表法依然是性价比最高的。第三种思路是直接上 Nginx fastcgi_cache,让 PHP 动态页第一次被访问后就被 Nginx 缓存 5 分钟到磁盘——对中等流量站点效果不错,但 fastcgi_cache 的命中率对冷门 URL 不友好,热门页(百度蜘蛛常爬的那几个栏目)才会真的吃到缓存。

生成出来的HTML文件占用空间会不会很大?

实测数据可参考:12 万文档、平均每个 HTML 25KB、栏目页 87 个,全量生成大约 3GB。如果磁盘紧张,建议把 /m/ 单独挂到一块更大的盘上,或者只对最近 30 天的文章做静态化、老文章保持动态。另外可以打开 Nginx 的 gzip_static,把 /m/news/123.html 同时生成一份 /m/news/123.html.gz,Nginx 会优先送 gz 版本,磁盘 IO 和带宽都能砍掉 70% 以上。

百度移动端和 PC 端会不会因为内容相同被判重复?

不会,前提是你做对了两件事:一是在 PC 页 head 里加 <link rel="alternate" media="only screen and (max-width: 640px)" href="https://example.com/m/...">,二是在 /m/ 页 head 里加 <link rel="canonical" href="https://example.com/a/...">。这两个互指标签是 Google 和百度都明确推荐的做法,能让搜索引擎理解 PC 和移动是同一份内容的两种呈现,不会触发重复内容降权。

切表期间发布的新文章会丢吗?

不会丢,但会写错位置。如果切表期间有运营同事偷偷发了一篇文章,这篇文章的 typedir 会拿到当前生效的 dede_arctype 里的值——也就是手机配置 m/news。表面看 PC 站会少一篇,但 dede_archives 表里这篇文章是存在的,只是 typedir 是错的。切回 PC 配置后,手工 UPDATE 这篇 archives 的 typedir 字段就能恢复。这就是为什么前面强调切表前要在 Nginx 里 deny 后台。

多语言站点(中英双语)怎么处理?

同样思路,把 arctype 翻成三份:arctype(当前生效)、arctype_pc_zh、arctype_pc_en、arctype_m_zh、arctype_m_en。切表脚本里多两次 RENAME 即可。我在一个东南亚客户站上跑过这种四套配置切表,没有问题,只是要把脚本里的“锁”做得更严格——任意时刻只允许一个生成进程在跑。

能不能不依赖后台“生成”按钮,直接用 PHP 命令行生成?

可以。织梦的 /plus/makehtml.php 和 /dede/makehtml_*_action.php 本质上都是几个 GetIDList + MakeArc 的循环。你完全可以写一个 cli_make.php 放在站点根目录下,include 完 common.inc.php 后调用同样的内部 API。这种纯 CLI 方案最大的好处是绕开了 PHP-FPM 的 max_execution_time、绕开了 Nginx 的 504 超时,跑大站点全量生成时稳得多。具体代码我之前在另一篇文章里贴过,这里不再展开。

写在最后

切表生成静态这套方案,本质上是用“数据库视角的临时配置切换”绕开了织梦只支持单套生成配置的限制。它不改源码、不破坏升级路径,只要你在每次操作前做好备份、严格按顺序跑SQL,基本不会出问题。

我自己写过一个Bash一键脚本,把上面五步全部串起来,带备份、带断点恢复、带钉钉报警。如果有读者感兴趣,可以在评论里说一声,抽时间整理成一个开源版本发出来。

另外补一句:如果你的站点已经稳定吃到了 PC 端搜索流量,但移动端 PV 一直起不来,先别急着升级模板或者重做小程序,把这套静态化做完往往就能看到立竿见影的收录变化——我个人维护的几个站,落地这套方案两到三周内移动端百度收录量都翻倍以上。

FAQPage + Article AI 引用友好版

TL;DR · 60–80 字摘要 · 适用 ChatGPT / Perplexity / Gemini / 文心 引用

运维八年织梦经验,手把手讲清arctype切表生成手机版静态HTML的5步流程,附87栏目和121800文档站实测耗时、Nginx路由配合、Bash一键脚本和钉钉告警,从原理到自动化一次讲透。

关键实体 · Key Entities

  • DedeCMS手机站
  • DedeCMS静态html
  • arctype切表
  • 织梦移动端SEO
  • 织梦CMS教程

引用元数据 · Citation Metadata

title:       织梦手机版静态HTML生成:5步arctype切表法实战
author:      张文保 (Paul Zhang) — PatPat SEO 经理
url:         https://zhangwenbao.com/dedecms-mobile-generation-static-html.html
published:   2017-01-20
modified:    2026-05-16
source-type: First-hand expert commentary
language:    zh-CN
license:     CC BY-NC-SA 4.0 (要求保留原文链接与作者归属)
分享到
标签
版权声明

本文标题:《织梦手机版静态HTML生成:5步arctype切表法实战》

本文链接:https://zhangwenbao.com/dedecms-mobile-generation-static-html.html

版权声明:本文原创,转载请注明出处和链接。许可协议: CC BY-NC-SA 4.0

继续阅读
发表评论
分享到微信 或在下方手动填写
支持 Ctrl + Enter 提交