ThinkPHP6 模板继承时我把 `layout` 放进了 `extend` 的 `block` 里,结果静态资源加载顺序变成了一场"俄罗斯轮盘"
上周给后台换主题,想搞个通用的 `layout.html` 做骨架,子页面用 `extend` 继承。本来觉得这事简单到闭眼写,结果资源路径的加载顺序把我整懵了整整一下午。
事情是这样的。我的 `layout.html` 里按常规思路放了 `block name="css"` 和 `block name="js"`,然后在 `` 末尾统一引入了一套基础样式——就是 AdminLTE 那套皮肤加上我自己封装的组件库。子页面 `dashboard.html` 继承之后,往 `css` block 里塞了几个页面级的样式,又额外在 `content` block 底部直接写了 ``。
本地测试一切正常,推到预发环境后,ECharts 的图表死活不渲染,控制台报 `echarts is not defined`。我第一反应是 CDN 挂了,结果刷新几次又能出来,再刷新又没了。
后来抓包才发现,ECharts 的加载时机在 `layout.html` 那套基础 JS 之前。因为子页面直接在 `content` 里硬编码了 script 标签,而 `layout.html` 的基础 JS 是写在 `` 前面的固定位置。模板继承之后,子页面的 `content` block 内容被填充到 `layout` 的对应位置,导致我那个手写的 script 跑到了 jQuery 和 AdminLTE 的初始化脚本前面。
更坑的是,我为了"省事",在 `layout.html` 里把 `__STATIC__` 解析成了 `/static/admin/`,而子页面里有个弹窗组件用了 `__STATIC__/module/dialog/`。预发环境的 Nginx 配置了静态资源缓存,路径带 `admin` 的走一台 OSS bucket,带 `module` 的走另一台。结果同一个 `__STATIC__` 前缀,在不同深度被解析后,一个加了版本号戳能刷新,另一个被 CDN 边缘节点缓存了旧文件。用户那边看到的页面,CSS 是新版的,JS 是旧版的,DOM 结构对不上,直接白屏。
我现在改成这样了:`layout.html` 里只保留 `block name="before_css"`、`block name="after_js"` 这种带明确位置的钩子,再也不在 `content` 中间任何地方直接塞 script。所有静态资源统一走模板里的 `block` 注入,哪怕是页面级的一行内联脚本,也给我老老实实塞进 `after_js` 里排队。
还有那个 `__STATIC__` 的问题,我在 `config/view.php` 里加了一层环境判断,预发和生产分别映射到不同的 CDN 域名,本地开发再走本地目录。之前图方便写死一个路径,现在每次发版都要手动清 CDN 缓存,纯属给自己挖坑。
模板继承这玩意,看起来是"套个壳就行",真玩起来才发现资源的加载顺序和发布路径是一体的。子页面里随手写的一个 script 标签,可能就把你 `layout` 里精心设计的依赖链打断。我现在每个 block 都起了带位置含义的名字,宁可名字长一点,也不想再玩一次加载顺序的抽奖。