[{"data":1,"prerenderedAt":339},["ShallowReactive",2],{"blog-trailing-slash-case-duplicate":3,"blog-prev-trailing-slash-case-duplicate":128,"blog-next-trailing-slash-case-duplicate":226},{"id":4,"title":5,"author":6,"body":7,"canonical":112,"category":113,"cover":112,"date":114,"description":115,"draft":116,"extension":117,"keywords":112,"meta":118,"navigation":119,"noindex":116,"ogImage":112,"path":120,"seo":121,"seoDescription":112,"seoTitle":112,"stem":122,"tags":123,"updated":112,"__hash__":127},"blog\u002Fblog\u002Ftrailing-slash-case-duplicate.md","尾斜杠和大小写：同一页面两个 URL 的隐形重复","元析智能",{"type":8,"value":9,"toc":101},"minimark",[10,14,18,21,25,37,40,43,62,65,68,71,82,85,88,92,95,98],[11,12,13],"p",{},"一个页面只应该有一个可访问的 URL 形式。尾斜杠、大小写、index.html、http 与 https、www 与非 www，这五类变体统一在服务器层 301，别让两个都保持 200。听起来是小事，但它造成的重复内容比参数还隐蔽。",[15,16,17],"h2",{"id":17},"为什么危险",[11,19,20],{},"搜索引擎需要判断哪个是主版本。外链和分享又散落在不同变体上，权重被切成几份。日志里抓取量被稀释，你以为是收录问题，其实是同一个页被当成三个页在抓。canonical 能救一部分，但它是建议不是强制，服务器层没统一就一直在漏。",[15,22,24],{"id":23},"_2026-年-1-月那次","2026 年 1 月那次",[11,26,27,28,32,33,36],{},"一个开发者工具站，文档页同时存在 ",[29,30,31],"code",{},"\u002FDocs\u002FAPI\u002F"," 和 ",[29,34,35],{},"\u002Fdocs\u002Fapi"," 两种形式，站内链接混用，外部链接也混着来。GSC 里 60% 的文档页报了\"重复网页，用户未选定规范网页\"。",[11,38,39],{},"统一成全小写、无尾斜杠之后，一个月重复网页从 60% 降到 8%，文档页的收录率从 55% 涨到 79%。改动就是 nginx 里三条规则。",[15,41,42],{"id":42},"五类变体的处理顺序",[44,45,46,50,53,56,59],"ol",{},[47,48,49],"li",{},"http 全部 301 到 https，一次跳到位。",[47,51,52],{},"裸域 301 到 www（或者反过来，选一个，别两个都行）。",[47,54,55],{},"大写 301 到小写。",[47,57,58],{},"尾斜杠统一：目录类路径统一无斜杠，或者统一带斜杠，二选一。",[47,60,61],{},"index.html 折叠到目录，301 过去。",[11,63,64],{},"顺序有讲究：先做协议和主机名，再做路径层。不然会出一条链跳三四次。",[11,66,67],{},"我们给客户定这条规则时，会顺手把 CDN 的缓存键也一起看：如果缓存键包含大小写或尾斜杠，同一个页面会在边缘节点缓存成多份，命中率下降，回源请求变多，本质上和重复 URL 是同一个问题。",[15,69,70],{"id":70},"服务器层怎么写",[11,72,73,74,77,78,81],{},"nginx 用 ",[29,75,76],{},"return 301"," 或 ",[29,79,80],{},"try_files"," 组合，Apache 用 mod_rewrite，CDN 层也要检查一遍，很多人只改了源站，边缘节点还返回旧结果。静态站生成器要统一 URL 输出规则，别让不同页面类型生成不同形式。",[15,83,84],{"id":84},"验证方法",[11,86,87],{},"curl 每个变体看返回码和 Location；Screaming Frog 爬一遍看有没有 301 和重复标题；GSC 网址检查确认 canonical 和最终 URL 一致。这三步花不到一小时。",[15,89,91],{"id":90},"和-canonical-的关系","和 canonical 的关系",[11,93,94],{},"服务器统一和 canonical 是两道防线，不是二选一。服务器层解决了大部分变体，canonical 兜住那些没法重定向的情况，比如参数变体、跨域镜像。只靠 canonical 不做重定向，蜘蛛每次还是会请求多个变体，抓取预算照样被切碎。",[15,96,97],{"id":97},"立场",[11,99,100],{},"这不是小事。一个站点三种 URL 形式，等于把权重分三份，再努力也是三分之一。统一规则的收益比多写十篇文章快。",{"title":102,"searchDepth":103,"depth":103,"links":104},"",2,[105,106,107,108,109,110,111],{"id":17,"depth":103,"text":17},{"id":23,"depth":103,"text":24},{"id":42,"depth":103,"text":42},{"id":70,"depth":103,"text":70},{"id":84,"depth":103,"text":84},{"id":90,"depth":103,"text":91},{"id":97,"depth":103,"text":97},null,"技术SEO","2026-05-23","\u002Fdocs\u002Fapi 和 \u002Fdocs\u002Fapi\u002F 是不是同一页，\u002FAbout 和 \u002Fabout 呢？这两类重复比参数更隐蔽。这篇给服务器层的统一规则、五类变体的处理顺序，以及一个 2026 年 1 月的修复记录。",false,"md",{},true,"\u002Fblog\u002Ftrailing-slash-case-duplicate",{"title":5,"description":115},"blog\u002Ftrailing-slash-case-duplicate",[124,125,126],"URL设计","重复内容",301,"jRlViDM6rOiCWw4iVh3ooY6pmG4fGkmXp82FxlJoabo",{"id":129,"title":130,"author":6,"body":131,"canonical":112,"category":113,"cover":112,"date":215,"description":216,"draft":116,"extension":117,"keywords":112,"meta":217,"navigation":119,"noindex":116,"ogImage":112,"path":218,"seo":219,"seoDescription":112,"seoTitle":112,"stem":220,"tags":221,"updated":112,"__hash__":225},"blog\u002Fblog\u002Fsoft-404-detection.md","软 404 比死链更伤：我们用日志抓出 3000 条并清完",{"type":8,"value":132,"toc":207},[133,136,140,143,146,149,152,155,158,161,164,168,171,174,177,180,183,186,189,192,195,198,201,204],[11,134,135],{},"软 404 是页面已经没了、服务器还返回 200，搜索引擎会一直抓、一直收、一直不给排名。我们用日志加状态码分布抓出 3000 条，清理后抓取频次涨了 55%。",[15,137,139],{"id":138},"什么是软-404","什么是软 404",[11,141,142],{},"用户和搜索引擎都以为页面还在，因为状态码是 200；但页面实际内容是\"暂无内容\"\"内容已删除\"\"加载失败\"。",[11,144,145],{},"常见的成因有三个：前端路由没配 404 兜底、CMS 删除文章后留了空模板、参数错误时返回了空列表页。",[11,147,148],{},"软 404 的坏处不是浪费一个页面，是让搜索引擎的索引里堆满空页面，连累整站质量判断。",[15,150,151],{"id":151},"我们怎么查",[11,153,154],{},"第一步，看日志里的状态码分布。如果 200 的请求占比超过 95%，而站点实际有大量已删除内容，就要怀疑。",[11,156,157],{},"第二步，抽样。从日志里随机抽 200 个返回 200 的 URL，用脚本抓页面正文，看正文长度和关键词。正文少于 100 字、或者标题里带\"未找到\"的，标记出来。",[11,159,160],{},"第三步，用 GSC 的\"已抓取但未编入索引\"报告交叉验证。这个报告里的页面，很多就是软 404。",[11,162,163],{},"2026 年 3 月我们给一个客户查的时候，抽样 200 个页面里有 37 个是软 404，按这个比例推算全站大约 1800 条。后来用脚本全量跑了一遍，实际 3100 条。",[15,165,167],{"id":166},"三类最常见的软-404","三类最常见的软 404",[11,169,170],{},"第一类，商品或功能下线的页面。产品下线了，页面还在，内容换成了\"该功能已调整\"。",[11,172,173],{},"第二类，参数错误的列表页。用户拼错参数，页面返回空列表，状态码 200。",[11,175,176],{},"第三类，前端路由的兜底页。SPA 里所有未匹配路由都渲染同一个空壳页，服务器返回 200。",[15,178,179],{"id":179},"修复顺序",[11,181,182],{},"先修影响大的：有外链指向的、还有搜索点击的、被收录的。这三类优先 301 到最相关的页面。",[11,184,185],{},"没有替代页面的，直接返回 410 或 404。别怕\"用户看到 404 不舒服\"，返回 200 的空页面更糟。",[11,187,188],{},"前端路由的兜底页要从根上改：未匹配路由返回 404，同时给用户一个可用的导航页。",[15,190,191],{"id":191},"修复后的数据",[11,193,194],{},"那个客户 3100 条软 404，我们清了 4 周。第 6 周看数据：抓取频次涨 55%，\"已抓取未编入索引\"从 1.1 万降到 4200，核心产品页的平均抓取间隔从 9 天缩到 3 天。",[11,196,197],{},"排名的变化慢一些，第 10 周才看到核心词平均提升 2.3 名。",[15,199,200],{"id":200},"判断",[11,202,203],{},"软 404 是技术 SEO 里最容易被忽略的一类，因为它不报错、不提醒、不影响用户。但它对抓取效率的损耗是实打实的。",[11,205,206],{},"每季度跑一次全量检查，比出事后再查便宜得多。这件事没有工具能一键完成，只能建自己的脚本，我们一般一天能跑完。",{"title":102,"searchDepth":103,"depth":103,"links":208},[209,210,211,212,213,214],{"id":138,"depth":103,"text":139},{"id":151,"depth":103,"text":151},{"id":166,"depth":103,"text":167},{"id":179,"depth":103,"text":179},{"id":191,"depth":103,"text":191},{"id":200,"depth":103,"text":200},"2026-05-22","软 404 是页面已经没了、服务器还返回 200，搜索引擎会一直抓、一直收、一直不给排名。我们用日志加状态码分布抓出 3000 条，清理后抓取频次涨了 55%。查法、分类和修复顺序都在这篇，清理前后的数据对比在文末，值得每季度跑一次。",{},"\u002Fblog\u002Fsoft-404-detection",{"title":130,"description":216},"blog\u002Fsoft-404-detection",[222,223,224],"软404","状态码","抓取","iGB0GXREiPW54w66EGO21t52OSD7aP1-21djciYKyWc",{"id":227,"title":228,"author":6,"body":229,"canonical":112,"category":113,"cover":112,"date":328,"description":329,"draft":116,"extension":117,"keywords":112,"meta":330,"navigation":119,"noindex":116,"ogImage":112,"path":331,"seo":332,"seoDescription":112,"seoTitle":112,"stem":333,"tags":334,"updated":112,"__hash__":338},"blog\u002Fblog\u002Fcache-three-layers.md","浏览器、CDN、服务端三层缓存，只配一层等于没配",{"type":8,"value":230,"toc":319},[231,234,237,240,243,246,249,252,255,258,261,265,268,271,274,277,280,283,286,289,292,295,298,301,304,307,310,313,316],[11,232,233],{},"2026 年 6 月我们接手一个站，首页加载 4.2 秒，查下来是缓存配反了：HTML 缓存一年，JS 和 CSS 缓存五分钟。用户每次访问都在重新下载样式和脚本，而首页本身永远是他一年前看到的版本。",[15,235,236],{"id":236},"三层缓存各管什么",[11,238,239],{},"浏览器缓存管单个用户，决定他第二次访问要不要重新下载。",[11,241,242],{},"CDN 缓存管一个区域的所有用户，决定请求要不要回到源站。",[11,244,245],{},"服务端缓存管数据，决定每次请求要不要查数据库、拼页面。",[11,247,248],{},"三层都配好，一个老用户访问首页可以只发一次 HTML 请求，其余全命中。",[15,250,251],{"id":251},"浏览器缓存怎么配",[11,253,254],{},"带内容哈希的静态资源，缓存一年，加 immutable。文件名变了 URL 就变了，不用担心更新问题。",[11,256,257],{},"HTML 不缓存或者只缓存几分钟。它是入口，缓存久了用户看不到新内容。",[11,259,260],{},"字体和图片可以长缓存，但要确认 URL 带版本或者哈希。",[15,262,264],{"id":263},"cdn-缓存怎么配","CDN 缓存怎么配",[11,266,267],{},"关键是缓存键。默认按 URL 缓存，如果 URL 里带了没意义的参数，缓存会被打散。",[11,269,270],{},"动态页面要么不缓存，要么用短时间加回源校验。我们一般给 HTML 设 5 分钟，给接口设不缓存。",[11,272,273],{},"还有一点，回源要带压缩。很多站 CDN 到源站这段没开 gzip，白白多传几倍数据。",[15,275,276],{"id":276},"服务端缓存怎么配",[11,278,279],{},"页面级缓存最有效，整页存起来，命中直接返回。",[11,281,282],{},"对象缓存其次，把数据库查询结果存内存。",[11,284,285],{},"数据变了要能主动清缓存，否则内容更新了用户还看到旧的。我们通常用版本号做键，发布时改版本号，旧缓存自然失效。",[15,287,288],{"id":288},"最常见的三种配错",[11,290,291],{},"第一种，就是开头说的两层配反。判断方法很简单，看响应头的 Cache-Control，HTML 和静态资源必须不一样。",[11,293,294],{},"第二种，静态资源文件名没哈希却设了长缓存。发版之后用户还跑旧代码，出了问题很难查。",[11,296,297],{},"第三种，CDN 缓存了带用户信息的页面。这个更危险，A 用户可能看到 B 用户的数据。",[15,299,300],{"id":300},"怎么验证配对了",[11,302,303],{},"用 curl 看响应头，重点看 cache-control、etag、age、x-cache 四个字段。",[11,305,306],{},"age 大于 0 说明命中了 CDN，x-cache 显示 HIT 或 MISS。连续请求同一个静态资源两次，第二次应该全是 HIT。",[11,308,309],{},"再打开 DevTools 的 Network 面板，看 Size 列有没有 from cache。这一步最直观。",[15,311,312],{"id":312},"一个态度",[11,314,315],{},"缓存是性价比最高的性能优化。改配置不写代码，效果立竿见影。",[11,317,318],{},"但它也是最容易出事故的地方。每次改缓存策略，尤其是 HTML 和带用户信息的页面，一定要先在测试环境验证，别直接调到生产。",{"title":102,"searchDepth":103,"depth":103,"links":320},[321,322,323,324,325,326,327],{"id":236,"depth":103,"text":236},{"id":251,"depth":103,"text":251},{"id":263,"depth":103,"text":264},{"id":276,"depth":103,"text":276},{"id":288,"depth":103,"text":288},{"id":300,"depth":103,"text":300},{"id":312,"depth":103,"text":312},"2026-05-24","静态资源该缓存一年，HTML 只该缓存五分钟。我们见过把两层配反的站，用户每次访问都在重新下载。这篇写三层各配什么、怎么配错。",{},"\u002Fblog\u002Fcache-three-layers",{"title":228,"description":329},"blog\u002Fcache-three-layers",[335,336,337],"缓存","CDN","页面体验","y2rj8uPfGTph9tGcf-y8gYIUZWoYf0TTatwwzpbQ9TM",1794088105390]