普通视图

发现新文章,点击刷新页面。
昨天 — 2025年12月4日首页

vue3 的预编译模板

作者 mangnel
2025年12月4日 10:15

在 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 项目为例,预编译流程如下:

  1. 开发/构建阶段: - 项目中的 .vue 文件会被 @vue/compiler-sfc(Vue 单文件组件编译器)处理; - 编译器解析 <template> 中的 HTML 结构、指令(v-if/v-for)、插值({{ }})等; - 将模板转换为 优化后的渲染函数(包含虚拟 DOM 创建逻辑、指令处理逻辑)。

  2. 运行时阶段: - 打包后的代码中,.vue 组件的 render 选项已直接是预编译好的函数; - Vue 运行时只需执行该函数,生成虚拟 DOM,再渲染为真实 DOM,无需额外编译步骤。

示例:模板 → 预编译后的渲染函数

原始模板(.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>

预编译后生成的渲染函数(简化版):

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 插件,即自动开启预编译:

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 限制的场景。

注意事项

  1. 仅支持静态模板:预编译仅对 .vue 文件中 <template> 标签的静态模板生效;若通过 template 选项传入动态字符串(如 template: '<div>{{ msg }}</div>'),仍会触发运行时编译(需引入完整 vue 包)。
// 不推荐:动态模板字符串,无法预编译,需运行时编译 
import { createApp } from "vue";
createApp({ 
  template: "<div>{{ msg }}</div>", // 运行时编译,需引入完整 vue 
  data() { return { msg: "Hello" }; }, 
}).mount("#app"); 
  1. 依赖构建工具:预编译依赖 Vite/webpack 等构建工具,纯 HTML 引入 Vue 3 时(如 <script src="vue.global.js"></script>),无法使用预编译,只能用运行时编译。

  2. 编译缓存:构建工具会缓存预编译结果,修改模板后需重新构建(开发环境热更新已自动处理)。

总结

Vue 3 的预编译模板,是将模板编译工作从“浏览器运行时”提前到“项目构建时”的优化技术。核心价值是 减小包体积、提升运行时性能、规避环境限制,且 Vue 3 生态的主流构建工具(Vite/Vue CLI)已默认集成,开箱即用。

简单说:预编译 = 提前编译模板 → 运行时直接用 → 更快、更小、更兼容

❌
❌