route:cache仅缓存routes/web.php和routes/api.php中的静态闭包路由,生成bootstrap/cache/routes-v7.php预编译数组,跳过动态注册、条件判断及注释,不兼容含闭包、类型提示错误、未绑定依赖或运行时函数的路由。

route:cache 命令到底缓存了什么
它只缓存 routes/web.php 和 routes/api.php 中的**静态闭包路由定义**,不处理动态注册(比如在服务提供者里用 Route::macro() 或循环生成的路由),也不包含 routes/channels.php 或 routes/console.php。
缓存后,Laravel 启动时不再逐行执行路由文件,而是直接加载一个预编译的 PHP 数组文件 bootstrap/cache/routes-v7.php(版本号随 Laravel 变化)。
- 只有
APP_ENV=production且APP_DEBUG=false时,框架才默认启用路由缓存逻辑 -
开发环境运行
php artisan route:cache会成功,但下次php artisan serve启动时可能因缓存未刷新而 404 - 缓存文件里没有注释、没有条件判断——所有
if (app()->environment('local')) { ... }这类逻辑都会被跳过
哪些路由写法会导致 route:cache 失败或失效
常见报错是 Unable to prepare route [xxx] for serialization. Uses Closure.,本质是 Laravel 无法序列化闭包。以下写法全部不兼容:
- 路由回调用闭包:
Route::get('/test', function () { return 'ok'; }); - 控制器方法带参数类型提示但类未自动加载(如写错命名空间,导致反射失败)
- 使用了未在容器中绑定的依赖,例如
Route::get('/', [SomeController::class, 'index'])->middleware(CustomMiddleware::class);而CustomMiddleware没有正确注册 - 路由中调用了运行时函数,如
Route::get('/time', function () { return now(); });
检查方法:运行 php artisan route:list --compact 看是否所有路由都显示为控制器方法格式(App\Http\Controllers\XController@y),而不是 Closure。
CI/CD 部署时 route:cache 的正确执行时机
必须放在「代码已同步完成、autoload 已更新、配置已写入」之后,且**早于 Web 服务器重启**。典型错误顺序是先 reload nginx,再跑 cache 命令,结果新路由根本没生效。
- 推荐部署脚本中按此顺序执行:
composer install --no-dev --optimize-autoloader→php artisan config:cache→php artisan route:cache→php artisan view:cache -
route:cache依赖config:cache,因为路由里可能用了config('app.name')这类读取配置的操作;如果配置没缓存,route:cache会 fallback 到未缓存状态 - 每次修改路由后,必须重新运行
php artisan route:cache,不能靠清空bootstrap/cache/目录来“刷新”
缓存后调试路由问题变得困难怎么办
缓存文件是纯数组,没法断点调试,也没法用 dd() 查看中间件堆栈。遇到 404 或中间件不触发,优先怀疑是不是缓存没更新或写法越界。
- 临时关闭缓存:删掉
bootstrap/cache/routes-v7.php,然后设APP_DEBUG=true再访问,错误会立刻暴露 - 想保留缓存又需要日志:在
app/Providers/RouteServiceProvider.php的boot()方法里加\Log::debug('Routes loaded');—— 注意这句必须写在parent::boot($router)之后,否则不会执行 - 复杂中间件逻辑(比如需读请求头、做鉴权分支)别塞进路由定义,应移到中间件类里处理,避免和缓存机制冲突
真正卡住的往往不是命令本身,而是缓存对“运行时行为”的零容忍——它只认确定性,不接受任何现场计算。











