编译流程与缓存 Compile Cache

编译流程与缓存 Compile Cache

DouView 是「按需编译 + 落盘缓存」的引擎:模板源只在必要时编译一次,产物写入编译目录,之后直接 include 执行。理解缓存的失效判据,能避免「改了模板不生效」「切了主题串页」这类问题。

一、渲染一个模板的完整流程

DouView::renderResource($resourceName) 的执行步骤:

1. resolveTemplatePath:把资源名解析为绝对路径(扩展名白名单 + 路径穿越/越界校验)
2. compilePath:算出该资源对应的编译产物路径
3. needsRecompile:判断是否需要重编(见下)
4. 若需要:读源 → runPrefilter → compile → 写入编译产物
5. include 编译产物(配合 RenderContext 输出)

二、是否需要重编(needsRecompile)

编译缓存的有效性由三个判据共同决定:

判据 行为
force_compile = true 每次请求都重编,忽略缓存(调试用,生产环境有性能代价)
编译产物不存在 首次访问必然重编
COMPILE_REVISION 版本头不匹配 编译产物头部写入修订号,与引擎常量不一致则重编
compile_check = true 且源 mtime 更新 源文件比编译产物新,则重编

其中 compile_check 默认为 true:开发期改完模板刷新即可生效;生产环境若追求极致性能可置 false,但那样改模板后必须手动清缓存。

三、COMPILE_REVISION —— 引擎级失效开关

DouView::COMPILE_REVISION(当前为 11)是一个「编译修订号」,与产品版本 VERSION(1.0)无关,专门用作缓存失效判据:

  • 每当编译语义或 Prefilter 行为发生变化,开发者会 bump 这个常量;
  • 旧编译产物头部的 rev 与新常量不一致,needsRecompile 返回真,全部模板自动重编;
  • 这保证了「引擎升级后无需手动清缓存也不会用旧语义渲染」。

四、前台的特殊性:theme_path 字面烘焙

前台预过滤器(FrontPrefilter)会在编译期把运行期的主题绝对路径字面烘焙进编译源——也就是说,编译产物里直接写死了当前主题的静态资源绝对路径。由此产生两个必须记住的结论:

  1. 编译缓存与主题强绑定:同一模板在不同主题下编译出的产物不同;
  2. 切主题 / 升级引擎后必须清缓存:切换站点主题时,系统会自动清理模板编译缓存(配合 COMPILE_REVISION 失效),否则可能渲染出旧主题的资源路径。

五、实践建议

  • 开发调试:保持 compile_check = true,改模板即时生效;若怀疑缓存串味,清空编译目录(compile_dir,默认 templates_c)后重试。
  • 上线部署:切换主题、覆盖模板文件、升级引擎后,清一次编译缓存最稳妥。
  • 排查「模板改了不生效」:依次确认——① 改的是当前生效主题下的文件;② compile_check 是否被关掉;③ 编译目录是否可写、是否残留旧产物。
添加日期: