ThinkPHP 优化需分前端资源合并与后端文件加载两方面:前端通过构建工具合并 CSS/JS 减少 HTTP 请求,后端通过 Composer 自动加载、OPcache 优化及配置精简降低 I/O 开销,并可提供聚合接口将多次 API 请求合并为一次。

ThinkPHP 本身是服务端框架,不直接产生前端 HTTP 请求,所谓“合并文件减少请求次数”,实际指的是优化前端资源加载(如 CSS、JS),或减少 PHP 自身的文件 I/O 和类加载开销。这两类“合并”目标不同、手段不同,需分开处理。
前端静态资源合并:减少浏览器 HTTP 请求
这是最常被问到的“减少请求次数”的场景。ThinkPHP 渲染的 HTML 页面若引入多个 CSS/JS 文件,浏览器就会发起多次请求。
-
合并 CSS 文件
- 把
header.css、user.css、common.css等手动或用工具合并为all.css - 在模板中只引入一次:
<link rel="stylesheet" href="/static/css/all.css"> - 推荐用构建工具自动化:
- Webpack:配置
mini-css-extract-plugin提取并合并 - Gulp:用
gulp-concat+gulp-clean-css - Vite:默认支持,
import './a.css'; import './b.css';构建后自动归并
- Webpack:配置
- 把
-
合并 JavaScript 文件
立即学习“PHP免费学习笔记(深入)”;
- 将通用工具库(如
utils.js)、业务逻辑(user-list.js)、初始化脚本(main.js)合并为app.js - 注意依赖顺序,避免运行时报错
- 启用压缩和 SourceMap(开发用),生产环境开启 Gzip/Brotli
- 将通用工具库(如
-
按需拆分,避免“全量加载”
- 后台管理页不需要移动端轮播组件,就别把
swiper.min.js打进app.js - 可配合 ThinkPHP 多应用机制(如
admin/api/index)分别打包对应资源
- 后台管理页不需要移动端轮播组件,就别把
PHP 层文件合并:降低服务端加载开销
这不是为了“减少 HTTP 请求”,而是减少 include/require 次数、类自动加载压力和 OPcache 编译负担。
-
慎用运行时
require大量文件- 避免在控制器或模型里反复
require 'xxx.php' - 改用 Composer 自动加载:把工具类放进
app/common/helper/,加 autoload 配置,让Helper\ExcelTool自动解析
- 避免在控制器或模型里反复
-
精简入口文件(
public/index.php)- 移除调试专用代码(如
define('APP_DEBUG', true)生产环境必须关) - 不要在此处
includePDF 生成器、Excel 解析器等重型类库 - 第三方 SDK 改用服务容器绑定 + 延迟实例化(
app()->make(Alipay::class))
- 移除调试专用代码(如
-
优化 Composer 自动加载
- 运行
composer dump-autoload --optimize生成高效类映射表,避免 PSR-4 实时扫描 - 删除未使用的包:
composer remove phpoffice/phpspreadsheet(如果项目已改用流式 CSV)
- 运行
-
配置文件合并(谨慎操作)
- ThinkPHP 默认加载
app.php、database.php、cache.php等多个配置文件 - 若项目结构简单,可将非敏感配置(如
paginate、template)合并进app.php,减少Config::load()调用次数 - ⚠️ 不建议强行合并数据库配置——它常需独立部署变量(如 Docker 环境注入)
- ThinkPHP 默认加载
补充:接口聚合也能“减少请求次数”
如果前端发了 5 个 API 请求(获取 banner、菜单、通知、用户信息、未读消息),可在 ThinkPHP 中提供一个聚合接口:
// app/api/controller/HomeController.php
public function index()
{
return json([
'banner' => BannerModel::limit(3)->select(),
'menu' => MenuModel::where('status', 1)->select(),
'notify' => NotifyModel::where('user_id', $this->uid)->limit(5)->select(),
'userinfo' => UserModel::find($this->uid),
'unread' => MessageModel::where(['to_id'=>$this->uid, 'read'=>0])->count(),
]);
}前端一次请求拿到全部数据,真正从「5 次请求」降到「1 次」。
不复杂但容易忽略



















