最靠谱方案是用 spatie/laravel-sitemap:它稳定、支持动态路由与多语言,生成静态 sitemap.xml 至 public/ 目录,非实时接口,需手动运行 php artisan sitemap:generate;务必过滤敏感路由、校验 URL 状态码与内容、同步配置 robots.txt 和 meta 标签。

生成 sitemap.xml 用 spatie/laravel-sitemap 最靠谱
直接上结论:别手写 XML,也别用过时的 laravel-sitemap(已多年未维护),spatie/laravel-sitemap 是当前 Laravel 生态里最稳定、支持动态路由、多语言、自定义优先级和最后修改时间的方案。
它底层用 SitemapGenerator 扫描路由或手动添加 URL,生成静态 sitemap.xml 文件到 public/,不走 PHP 动态渲染,速度快、CDN 友好、搜索引擎也认。
常见错误是把它当“实时接口”用——比如每次请求都调用 SitemapGenerator::create(),这会严重拖慢响应,还可能因并发写文件出错。它本就是构建时工具,不是运行时中间件。
- 安装后必须运行
php artisan sitemap:generate才生成文件,不会自动触发 - 动态内容(如文章、商品)需在生成前主动调用
add()注入,不能只依赖generateFromApp() - 多域名项目要显式传
https://example.com到create(),否则默认用config('app.url'),容易混掉子站 - 如果用了 Cloudflare 或 Nginx 缓存,记得清掉
/sitemap.xml的缓存,否则更新后搜索引擎抓不到新版本
Laravel 路由太多时,别全塞进 sitemap
一个典型坑:用 generateFromApp() 扫描所有路由,结果把 login、logout、password/reset 全塞进 sitemap,Google 抓取后标记为“低质量页面”,反而影响收录权重。
真正该进 sitemap 的只有:公开、有内容、SEO 目标页(首页、分类页、详情页、博客列表/文章)。其他一律过滤。
- 用
ignoreRoutes()明确排除后台、API、认证相关路由名,例如:ignoreRoutes(['login', 'admin.*', 'api.*']) - 对资源路由(
PostController@destroy)这类非展示型动作,哪怕没显式命名,也要在routes/web.php中加注释或分组隔离,方便后续识别 - 如果用
Route::middleware('auth')包裹整组路由,基本可判定不该进 sitemap——除非是会员专属内容页且你明确要索引 - 检查生成后的
sitemap.xml,用浏览器打开看有没有/logout?next=%2F这类带参数的脏 URL,有就说明路由扫描没过滤干净
动态内容(如文章)怎么安全加进 sitemap
文章、商品这些数据变频繁,但 sitemap 不适合每改一条就重生成——IO 高、易冲突、无必要。合理做法是按频率分层处理:高频更新用 sitemap-index.xml 拆分,低频直接合并。
Laravel Cloud(cloud.laravel.com)。此技能用于处理所有 Laravel Cloud 请求,包括搜索和读取数据。只要任务涉及 Laravel Cloud,即使用此技能。
核心原则:URL 必须真实可访问、状态码是 200、内容不为空。否则 Google 会降权整个 sitemap。
- 在
php artisan sitemap:generate命令中调用add()时,确保模型查询加了where('published', true)和whereNotNull('slug')等必要条件 - 避免在
add()里做 N+1 查询,比如循环查每个文章的封面图 URL;应提前用with('media')预加载,或直接从字段取路径 - 时间戳用
$post->updated_at->tz('UTC'),别用本地时区,否则 Google 抓取时可能误判“内容陈旧” - 优先级(
priority)别全设成1.0,首页1.0、栏目页0.8、文章页0.7更符合实际权重分布
SEO 不只是 sitemap:robots.txt 和 meta 标签得同步配
光有 sitemap 不等于 SEO 做完了。Google 会先读 robots.txt 再决定要不要抓,而页面 meta 标签决定了它怎么展示摘要——这两块漏掉,sitemap 就是单机房里的豪华电梯,没人按楼层键。
常见疏忽是本地开发时关了 APP_ENV=local 下的 robots.txt,上线后忘记开,结果整站被 Disallow: / 拦死。
-
public/robots.txt至少要有:User-agent: *和Sitemap: https://yoursite.com/sitemap.xml,其他行按需加Disallow - 模板里用
@yield('meta'),在文章页@section('meta')插入,别依赖 Laravel 默认的空 description - 不要在 Blade 中用
这种 fallback,万一{{ $title ?? 'Default' }} $title是 null,页面标题就裸奔成 “Default”,毫无关键词 - 检查生产环境是否启用了
APP_DEBUG=false,否则 Laravel 错误页可能暴露路由结构,被恶意爬虫利用
sitemap 的关键不在“生成”,而在“谁生成、什么时候生成、生成完有没有人真去查”。定时任务跑得再勤,如果 robots.txt 拦着、页面返回 404、meta 描述全是 Lorem ipsum,那 XML 文件再标准也没用。










