ThinkPHP需手动解析Vite生成的manifest.json实现资源哈希映射:开发时直连Vite服务器,生产时通过json_decode读取public/build/manifest.json,结合环境变量动态注入带hash的CSS/JS路径,注意base配置、权限及路径拼接。

ThinkPHP如何读取Vite生成的manifest.json
ThinkPHP本身不自动识别Vite的资源哈希映射,必须手动解析public/build/manifest.json并注入到模板中。直接写死index.css或index.js会导致缓存失效或404——Vite开启build.rollupOptions.output.entryFileNames后,真实文件名带hash,比如index.ABC123.js。
实操建议:
立即学习“PHP免费学习笔记(深入)”;
- 确保Vite构建时启用
build.manifest: true,输出public/build/manifest.json - 在ThinkPHP控制器或公共函数里用
json_decode(file_get_contents(public_path('build/manifest.json')), true)读取 - 注意路径:ThinkPHP的
public_path()对应public/目录,manifest默认在public/build/下 - 若Vite配置了
build.outDir: 'public/static',则需同步调整读取路径为public/static/manifest.json
如何在ThinkPHP模板中动态引入Vite的CSS和JS
不能直接写<link rel="stylesheet" href="/build/index.css">,得从manifest.json里查出带hash的真实文件名。关键点是区分入口chunk和异步chunk——manifest.json里只有入口(如index.html对应的entry)才保证有css和imports字段。
实操建议:
立即学习“PHP免费学习笔记(深入)”;
- 入口HTML对应manifest里的key通常是
index.html(不是index.js),它的assets数组含所有直接依赖的CSS/JS - 推荐在模板中用
{:get_vite_asset('index.html', 'css')}这类自定义函数封装逻辑,避免模板里堆JSON操作 - 如果用了
build.rollupOptions.output.manualChunks,部分CSS可能不在入口assets里,得遍历整个manifest找isEntry: true且file以.css结尾的项 - JS同理,但要注意
type: "module",所以<script type="module" src="...">不能省
为什么manifest.json里找不到CSS或JS?
常见错误现象:json_decode后得到空数组、assets为空、或者根本没css字段——大概率是Vite配置或构建流程没对上。
原因和对策:
- Vite 5+ 默认
build.cssCodeSplit: true,CSS被拆成独立文件但不一定挂到入口下;检查manifest里是否有.css文件且isEntry为true - 没在
vite.config.ts里配build.rollupOptions.input指向实际入口HTML(如src/index.html),会导致manifest不生成对应条目 - ThinkPHP运行环境是PHP-FPM,而Vite开发服务器(
vite dev)不生成manifest;只在vite build后才有,别在开发环境硬读manifest - 权限问题:
public/build/manifest.json被gitignore或部署脚本漏传,PHP读不到文件,file_get_contents返回false,记得加if (!$manifest)判空
如何兼容Vite的热更新开发模式与生产构建模式
开发时不该读manifest,该走http://localhost:5173/@vite/client和/src/main.ts;生产才走manifest。这个切换逻辑最容易被忽略,硬编码会卡死调试。
实操建议:
立即学习“PHP免费学习笔记(深入)”;
- 用环境变量区分:
App.env('app_debug')为true时,模板直接输出<script type="module" src="http://localhost:5173/@vite/client"></script>+<script type="module" src="http://localhost:5173/src/main.ts"></script> - 生产环境再走manifest解析流程,两者完全隔离
- 别试图在开发时“模拟”manifest内容,Vite dev server的资源路径和build产物结构完全不同,模拟只会埋坑
- 如果用了
vite-plugin-legacy,manifest里会出现legacy-polyfills等额外条目,要过滤掉非isEntry的项,否则引入多余JS
最麻烦的其实是路径拼接:Vite的base配置(比如设为/subpath/)会影响manifest里所有file字段的值,PHP读出来后得手动补前缀,否则404。这个细节,上线前常被跳过。



















