在 Vue 3 中,预编译模板(Precompiled Templates) 是指在 构建阶段 就将 Vue 模板(<template> 中的内容)编译为渲染函数(Render Function),而非在浏览器运行时动态编译的技术。其核心目标是优化性能、减少运行时开销,并规避浏览器环境的编译限制。
一、先明确:模板的两种编译方式
Vue 模板要被浏览器执行,最终必须转为 JavaScript 渲染函数(虚拟 DOM 描述)。编译过程分两种:
| 类型 | 编译时机 | 执行环境 | 核心特点 |
|---|---|---|---|
| 运行时编译(Runtime) | 浏览器运行时 | 浏览器 | 模板字符串 → 渲染函数,需带编译器,体积大 |
| 预编译(Precompile) | 项目构建阶段 | 构建工具(webpack/vite) | <template> → 渲染函数,运行时无需编译器 |
| Vue 3 的预编译模板,本质就是选择"构建时编译",提前完成模板到渲染函数的转换。 |
二、预编译模板的核心作用
1. 减小运行时体积
Vue 3 的核心包分为两种:
vue:包含编译器 + 运行时(体积较大,约 10KB+ 额外开销);-
@vue/runtime-dom:仅包含运行时(体积更小,约 3KB+)。 预编译后,项目运行时无需编译器,可直接引入@vue/runtime-dom,大幅减小最终打包体积(尤其对小型项目/移动端友好)。
2. 提升运行时性能
模板编译是耗时操作(需解析 HTML 字符串、处理指令/插值、生成渲染函数)。预编译将这一步移到构建阶段,浏览器运行时直接执行现成的渲染函数,避免了 runtime 编译的性能开销,首屏渲染和组件更新速度更快。
3. 规避浏览器环境限制
运行时编译依赖 new Function() 解析模板,部分严格的浏览器安全策略(如 CSP 限制)会禁止该 API,导致模板无法编译。预编译生成的是纯 JS 函数,无此限制,兼容性更优。
4. 更早发现模板错误
编译过程中会校验模板语法(如闭合标签、指令格式、变量引用),错误会在构建阶段抛出(而非运行时),便于更早排查问题。
三、预编译模板的工作原理
以 Vue 3 + Vite 项目为例,预编译流程如下:
-
开发/构建阶段 : - 项目中的
.vue文件会被@vue/compiler-sfc(Vue 单文件组件编译器)处理; - 编译器解析<template>中的 HTML 结构、指令(v-if/v-for)、插值({{ }})等; - 将模板转换为 优化后的渲染函数(包含虚拟 DOM 创建逻辑、指令处理逻辑)。 -
运行时阶段 : - 打包后的代码中,
.vue组件的render选项已直接是预编译好的函数; - Vue 运行时只需执行该函数,生成虚拟 DOM,再渲染为真实 DOM,无需额外编译步骤。
示例:模板 → 预编译后的渲染函数
原始模板(.vue 文件):
.vue
<template>
<div class="greeting">
Hello, {{ name }}!
<p v-if="show">Vue 3 预编译模板</p>
</div>
</template>
<script setup>
const name = "Vue";
const show = true;
</script>
预编译后生成的渲染函数(简化版):
javascript
import { createVNode as _createVNode, toDisplayString as _toDisplayString, openBlock as _openBlock, createBlock as _createBlock } from "@vue/runtime-dom";
export function render(_ctx, _cache, $props, $setup, $data, $options) {
return _openBlock(), _createBlock(
"div",
{ class: "greeting" },
[
_createVNode("text", null, "Hello, " + _toDisplayString(_ctx.name) + "!"), _ctx.show
? _createVNode("p", null, "Vue 3 预编译模板")
: _createVNode("text", null, "")
]
);
}
运行时 Vue 直接执行 render 函数,无需解析模板字符串。
四、如何启用预编译模板?
Vue 3 项目(尤其是 Vite 或 Vue CLI 搭建的项目)默认已启用预编译,无需额外配置:
-
Vite:内置
@vitejs/plugin-vue,自动处理.vue文件的模板预编译; -
Vue CLI:基于 webpack,通过
vue-loader集成@vue/compiler-sfc,自动预编译模板。
关键配置验证(以 Vite 为例)
vite.config.js 中只需引入 Vue 插件,即自动开启预编译:
javascript
import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";
// 自动处理 .vue 模板预编译 export default defineConfig({ plugins: [vue()], });
手动确认预编译生效
-
打包后查看输出的 JS 文件,不会包含
vue核心包(而是@vue/runtime-dom); -
组件代码中无模板字符串,直接是
render函数。
五、预编译的适用场景与注意事项
适用场景 - 绝大多数 Vue 3 项目(尤其是生产环境),优先使用预编译;
-
对包体积、性能敏感的场景(如移动端、小程序);
-
存在浏览器 CSP 限制的场景。
注意事项
- 仅支持静态模板 :预编译仅对
.vue文件中<template>标签的静态模板生效;若通过template选项传入动态字符串(如template: '<div>{{ msg }}</div>'),仍会触发运行时编译(需引入完整vue包)。
javascript
// 不推荐:动态模板字符串,无法预编译,需运行时编译
import { createApp } from "vue";
createApp({
template: "<div>{{ msg }}</div>", // 运行时编译,需引入完整 vue
data() { return { msg: "Hello" }; },
}).mount("#app");
-
依赖构建工具 :预编译依赖 Vite/webpack 等构建工具,纯 HTML 引入 Vue 3 时(如
<script src="vue.global.js"></script>),无法使用预编译,只能用运行时编译。 -
编译缓存:构建工具会缓存预编译结果,修改模板后需重新构建(开发环境热更新已自动处理)。
总结
Vue 3 的预编译模板,是将模板编译工作从"浏览器运行时"提前到"项目构建时"的优化技术。核心价值是 减小包体积、提升运行时性能、规避环境限制,且 Vue 3 生态的主流构建工具(Vite/Vue CLI)已默认集成,开箱即用。
简单说:预编译 = 提前编译模板 → 运行时直接用 → 更快、更小、更兼容。