必须预编译handlebars模板,否则runtime编译导致卡顿和内存泄漏;浏览器端仅引入runtime.js;partial需全局一次性注册并显式注销;helper须纯计算无副作用;dom结构臃肿比模板更拖慢首屏。

Handlebars 预编译模板必须做,否则 runtime 编译吃内存
不预编译的 Handlebars.compile() 每次调用都会解析字符串、生成 AST、再转成函数,这个过程在低端设备上可能卡顿 50ms+,且每次生成的新函数无法被 GC 回收干净,容易累积内存。生产环境必须用预编译。
实操建议:
- 用命令行工具统一预编译:
npx handlebars templates/ -f templates.js,输出的是纯函数数组,不含编译器逻辑 - 浏览器端只引入
handlebars.runtime.js(约 4KB),而非完整版handlebars.js(约 25KB) - 避免在循环中动态拼接模板字符串再调用
compile()——这是内存泄漏高发场景 - 预编译产物需配合
Handlebars.registerPartial()手动注册部分模板,不能依赖运行时自动发现
Partial 模板注册方式影响渲染速度和内存驻留
重复注册同名 partial(比如在组件 mount 时每次都 Handlebars.registerPartial('item', template))会导致旧引用残留,新函数不断叠加,GC 无法清理。更糟的是,未清理的 partial 会持续占用模板缓存空间。
实操建议:
- 全局 partial 在应用初始化时集中注册一次,不要在组件生命周期内反复注册
- 按需加载的 partial(如弹窗模板)应使用唯一 key 注册,并在销毁时显式调用
Handlebars.unregisterPartial('modal-xxx') - 避免把整个数据上下文传给 partial:用
{{> item item=item}}而不是{{> item}},减少作用域链遍历开销 - partial 文件名不能含空格或特殊字符,否则预编译时会被忽略,运行时报
Missing helper: "xxx"
自定义 Helper 函数别在内部做 DOM 操作或深克隆
Helper 是模板执行时同步调用的函数,任何耗时操作都会阻塞渲染。常见错误是把 document.querySelector、JSON.parse(JSON.stringify()) 或复杂正则塞进 helper 里,导致 LCP 延迟明显。
实操建议:
- helper 只做纯计算:格式化日期、拼接字符串、布尔判断——所有输入必须是原始值或扁平对象
- 需要 DOM 交互的逻辑,提前在数据层处理好,通过 context 传入模板,而不是让 helper 去查
- 避免在 helper 中创建闭包或绑定 this,这会阻止 V8 优化,实测使渲染变慢 15%~20%
- 用
Handlebars.registerHelper('fmt-date', (ts) => new Date(ts).toLocaleString())这类无副作用写法最安全
HTML 本身结构臃肿比模板引擎更拖慢首屏
很多人盯着 Handlebars 性能调优,却忽略一个事实:一个嵌套 8 层的 <div class="container"><div class="row"><div class="col">…</div></div></div>,即使模板渲染快,DOM 构建和 layout 仍要多花 30ms+。尤其在低端安卓 WebView 中,DOM 节点数超 1500 就开始明显掉帧。
实操建议:
- 删掉所有无语义的包装 div,用
display: contents或 flex/grid 替代层级 - 服务端返回的 HTML 不要带 placeholder 类(如
<div class="loading"></div>),改用 CSS:has()或 JS 控制显隐 -
<script></script>标签必须加defer或放
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











