Nova 本身不是性能瓶颈,但其默认行为会放大N+1查询、无分页、全量字段等已有问题;优化核心是约束数据请求,手动在indexQuery()和fields()中预加载、字段裁剪、分页及禁用冗余功能。

Nova 本身不是 Laravel 性能瓶颈的根源,但它的默认行为会放大已有问题——比如未预加载的关联、全量字段查询、无分页的资源列表、高频轮询或未关闭的调试工具。优化 Nova 的核心是「约束它的数据请求」,而不是给它单独加缓存或改源码。
为什么 Nova 页面卡顿得比普通路由还明显
Nova 资源索引页默认调用 indexQuery() + fields() + 每行渲染时触发 resolveForDisplay(),中间可能穿插多次模型访问;更关键的是,它不自动预加载任何关系,也不限制字段。一个 UserResource 列出 50 条用户,却在每行都读 $user->posts()->count(),就会触发 50 次额外查询。
- 常见错误现象:
DB::listen()显示索引页执行了 120+ 查询,其中 90% 是重复的select * from posts where user_id = ? - 使用场景:后台用户管理、订单列表、内容审核页等需快速浏览大量记录的界面
- 性能影响:单页加载从 800ms 增至 4.2s,内存占用翻倍,PHP-FPM worker 容易超时
必须重写 indexQuery() 和 fields() 里的 Eloquent 调用
Nova 不会帮你做预加载或字段裁剪,所有优化要手动塞进资源类里。重点不是“怎么写 Nova”,而是“怎么让 Nova 发出的 SQL 更干净”。
-
indexQuery()中强制使用with()和select():例如return $query->with('role')->select('id', 'name', 'email', 'role_id'); -
fields()里避免在Text::make('Posts Count')中写闭包去查数据库;改用已预加载的属性:Text::make('Posts Count', function () { return $this->posts_count ?? 0; }),并在indexQuery()中补上withCount('posts') - 不要在
fields()里调用$this->relation->name—— 这会触发懒加载;确保关联已在indexQuery()预加载,再用$this->relation->name - 对大数据集,必须加
->latest()->paginate(25);Nova 默认用get(),一旦记录超 500 条,内存直接爆掉
禁用 Nova 自带的软删除/搜索/过滤器等“便利功能”
这些功能看似省事,实则悄悄增加查询负担:搜索框每次输入触发全表 LIKE 查询;过滤器默认对每个字段加 whereNotNull();软删除开关强制加 where deleted_at is null 并多一次 count 查询。
- 关闭方法:在资源类顶部加
public static $globallySearchable = false;、public static $searchRelations = []; - 如需搜索,改用 Algolia 或 Scout,别依赖 Nova 内置搜索
- 过滤器只保留真正需要的字段,删掉
DateFilter::make('Created At')这类通用项(它们没索引,查得极慢) - 如果业务不需要软删除,直接在
indexQuery()移除withTrashed()或onlyTrashed()调用
生产环境必须关掉 Nova 的调试面板和前端监控
Nova 开发时默认启用 Nova::servesScout()、Nova::script() 等前端埋点,还会在响应头注入 X-Nova-Version 和大量 JSON 元数据。这些在生产环境毫无价值,纯属拖慢首屏。
- 检查
config/nova.php中'enable' => env('NOVA_DEBUG', false),确保NOVA_DEBUG=false在 .env 生产环境生效 - 移除
App\Providers\NovaServiceProvider中的Nova::script('nova-debugbar', ...)类似代码 - 禁用前端资源版本控制:在
resources/js/nova-components/下删掉DebugPanel.vue引用(如果自定义过) - 最彻底的方法:部署时用
--no-dev安装依赖,并确认composer.json的require-dev里没包含laravel/nova(它应只在本地安装)
真正容易被忽略的是:Nova 的性能问题几乎从不来自 Nova 本身,而是暴露了你 Eloquent 层长期存在的 N+1 和无索引查询。修复它,等于顺手把整个后台的数据链路都理清楚了。











