路由缓存需在生产环境(APP_ENV=production且APP_DEBUG=false)下执行php artisan route:cache,将routes/web.php和routes/api.php中静态定义的控制器路由编译为bootstrap/cache/routes-v8.php文件,后续请求直接加载该文件以提升性能;闭包路由、Route::fallback()、动态注册或条件包裹的路由均不被缓存,否则导致404或Class not found。

路由缓存不是“开个开关就提速”,而是把 routes/web.php 和 routes/api.php 里所有静态注册的路由,编译成一个 PHP 数组文件(比如 bootstrap/cache/routes-v8.php),后续请求直接加载它,跳过逐行解析。但一旦用错,新路由不生效、404、Class not found 都会悄无声息地发生。
route:cache 命令执行前必须满足的条件
这个命令不会帮你兜底,它只认硬性规则:
-
APP_ENV=production且APP_DEBUG=false—— 开发环境默认拒绝执行,强行改环境变量绕过会导致缓存内容不可靠 - 所有路由必须是
Route::get()、Route::post()这类顶层调用,不能藏在中间件、服务提供者或if条件块里(例如if (app()->environment('local')) { Route::get(...) }) - 不能有闭包路由:
Route::get('/', function () { ... })会被静默跳过,上线后访问就是 404 - 不能有
Route::fallback()—— 它不进缓存,清完缓存再跑一次route:list就能发现它消失了 -
bootstrap/cache/目录需对 Web 服务器用户(如www-data)可读,但不应可写
为什么 route:cache 后路由突然 404?常见排查点
这不是缓存“坏了”,而是缓存忠实地反映了你当前代码的状态:
- 运行
php artisan route:list --compact,看输出里有没有Closure或fallback—— 有就说明它们没被缓存,但你却依赖它们响应请求 - 检查控制器方法是否存在:缓存后
App\Http\Controllers\UserController@missingMethod这种拼写错误不会在route:cache阶段报错,而是在第一次访问时抛Method does not exist - 如果你同时用了
config:cache,而路由里写了middleware(config('auth.defaults.guard'))这类动态引用,缓存生成时会取构建时刻的配置值,不是运行时的 - 部署时 CI/CD 脚本在代码同步前就跑了
route:cache,缓存文件指向旧版本控制器路径,结果 Class not found
route:clear 不是“重启”,只是删文件
php artisan route:clear 做的唯一一件事,就是删除 bootstrap/cache/routes-v8.php(或类似命名)。它不 reload 任何服务,也不重载路由定义:
- 删完之后,下一次 HTTP 请求进来,Laravel 才会重新解析
routes/*.php—— 所以你要确保这些文件语法正确,否则直接 500 - 它不清理
config.php或view缓存,改了中间件名或视图路径,得额外跑config:clear和view:clear - 在 Forge / Vapor 等托管平台,
route:clear只影响当前执行的机器,如果缓存写在共享卷或容器镜像里,本地执行无效 - 别指望浏览器刷新就能看到效果:Nginx 可能 301 重定向了旧路径,或者前端 SPA 的 history 模式缓存了上一个 404 页面
Laravel 12+ 的 route:cache:optimize 更激进
这个命令不是简单升级版,它是另一套机制:预编译正则、扁平化路由结构、剔除所有运行时分支判断:
- 它要求所有路由定义必须“完全静态”——连
Route::middleware(app()->environment() === 'staging' ? ['throttle'] : [])这种都不行 - 生成的缓存文件带哈希索引,匹配更快,但容错更低;一旦失败,
route:list会直接报错退出,而不是静默跳过 - 目前不兼容任何含
request()、session()、auth()调用的路由闭包或控制器构造函数逻辑 - 只推荐用于高并发、纯 API 场景;Web 应用里混着 Blade 渲染和 session 交互,用它反而容易踩坑
最常被忽略的一点:路由缓存文件是 PHP 代码,不是 JSON 或序列化字符串。它被 require 进来,所以任何写死在缓存里的路径、类名、中间件别名,都必须和当前部署代码完全一致——差一个命名空间斜杠,就 Class not found。



















