vue3tohtml
vue3tohtml
将 Vue 3 单文件组件 (.vue) SSR 渲染为纯静态 HTML——不含任何 JavaScript, 打开即有完整内容,无头浏览器截图、缩略图生成、静态预览的首选方案。
特性
- ✅ 支持完整的 Vue 3 模板语法(v-if / v-for / v-model / v-html / 插值)
- ✅ 支持
<script setup>+ Composition API(ref / computed / watch) - ✅ 支持 TypeScript(类型注解自动剥离)
- ✅ scoped 样式在静态输出中真实生效
- ✅ 零 JavaScript 产物:无网络请求、无 JS 执行、无白屏等待
- ✅ 内容哈希缓存:首次渲染 ~150ms,同组件再次渲染 < 1ms
架构
调用方(Node 脚本 / Express / Puppeteer)→ index.ts(API 入口)→ ssr.ts(渲染层:缓存查询、组件求值、renderToString)→ compiler.ts(编译层:compileSFC、scoped 样式、TS 剥离)→ 纯静态 HTML。缓存命中时跳过编译与求值,直接复用已求值的组件模块(<1ms)。
交互版(深浅色切换、导出 PNG/SVG):docs/architecture.html
安装
# 作为 npm 包使用(发布后)
npm install vue3tohtml
# 本地开发
pnpm install
npm run build # 构建 dist/(发布产物)
快速开始
import { writeFile } from 'fs/promises'
import { compileVueToStaticHTML } from 'vue3tohtml'
// 传 .vue 文件路径,返回静态 HTML 字符串
const html = await compileVueToStaticHTML('./App.vue', {
title: 'My Demo', // 可选,不传默认取文件名(App.vue → App)
})
await writeFile('output.html', html)
// 浏览器打开 output.html:完整内容 + 样式,零 JS、零网络依赖
API
| 函数 | 说明 |
|---|---|
compileVueToStaticHTML(filePath, options?) |
从 .vue 文件渲染完整静态 HTML |
compileVueToStaticHTMLFromCode(code, options?) |
从 SFC 源码字符串渲染完整静态 HTML |
renderVueToString(code, options?) |
渲染为 HTML 片段 + 样式(无文档壳),适合直接喂无头浏览器 |
compileSFC(source, options?) |
编译为编译结果对象 { script, styles, scopeId, descriptor } |
generateStaticHTML(appHtml, styles, options?) |
片段 + 样式组装为 HTML 文档 |
选项(所有渲染函数通用):
interface RenderOptions {
title?: string // 页面标题。文件路径 API 不传时默认取文件名;
// 源码 API 不传时默认 'Vue SFC Preview'。会被 HTML 转义
filename?: string // 文件名,用于错误提示与样式预处理
props?: Record<string, unknown> // 传给根组件的 props(JSON 对象),
// 组件内用 defineProps 接收,每次调用独立生效
}
传入 props(每次调用可传不同 JSON 数据):
import { compileVueToStaticHTMLFromCode } from 'vue3tohtml'
// 组件内用 defineProps 声明接收
const code = `
<script setup lang="ts">
defineProps<{ user: { name: string; tags: string[] } }>()
</script>
<template>
<h1>{{ user.name }}</h1>
<ul><li v-for="tag in user.tags" :key="tag">{{ tag }}</li></ul>
</template>`
const html = await compileVueToStaticHTMLFromCode(code, {
props: { user: { name: 'Alice', tags: ['a', 'b'] } },
})
同一组件(源码不变)每次调用传不同的 props 会得到不同渲染结果——模块缓存只复用编译产物,setup() 每次渲染重新执行,无状态残留。
使用场景
场景一:批量截图 / 缩略图
import { compileVueToStaticHTMLFromCode } from 'vue3tohtml'
const components = [code1, code2, code3] // SFC 源码数组
const pages = await Promise.all(
components.map(code => compileVueToStaticHTMLFromCode(code)),
)
// 逐个交给无头浏览器截图;同组件重复渲染走缓存(<1ms)
场景二:Puppeteer 直喂(不写临时文件)
import { renderVueToString } from 'vue3tohtml'
const { appHtml, styles } = await renderVueToString(vueCode)
const css = styles.map(s => s.code).join('\n')
await page.setContent(`<!DOCTYPE html><html><head><style>${css}</style></head>
<body><div id="app">${appHtml}</div></body></html>`)
const screenshot = await page.screenshot()
场景三:HTTP 渲染服务(Express)
import express from 'express'
import { compileVueToStaticHTMLFromCode } from 'vue3tohtml'
const app = express()
app.use(express.json())
app.post('/api/render', async (req, res) => {
try {
const html = await compileVueToStaticHTMLFromCode(req.body.code)
res.type('html').send(html)
} catch (error) {
res.status(400).json({ error: (error as Error).message })
}
})
app.listen(3000)
支持的 Vue 特性
| 类别 | 支持情况 |
|---|---|
| 模板语法 | 插值、v-if / v-for / v-model / v-html、class / style 绑定 |
| Script | <script setup>、Composition API(ref / reactive / computed / watch) |
| TypeScript | lang="ts" 类型注解自动剥离(as 断言、泛型、interface 等全支持) |
| 样式 | scoped CSS(静态输出中真实生效)、CSS 预处理器(需额外安装 sass/less) |
| 无 script 组件 | 纯 template 的 .vue 同样可渲染 |
限制与注意事项
产物是静态快照:
onMounted等浏览器生命周期不执行、事件绑定(@click 等)不生效- setup 顶层不能访问
window/document(Node 环境没有;放进onMounted即可) - 插值、computed、v-for 等渲染时求值的特性全部正常
安全(重要): 渲染会在 Node 进程内执行 SFC 中的脚本代码。 如果组件来源不可信(用户提交、AI 生成),请在隔离环境(容器、独立 worker)中运行。
常见问题:
- 需要 CDN 或网络吗? 不需要,所有渲染在 Node 内完成,产物自包含
- 生成的 HTML 可以部署吗? 可以,直接扔到任何静态服务器
- 如何自定义基础样式? 修改
src/ssr.ts中的BASE_STYLES后重新 build
开发
npm run typecheck # TypeScript 类型检查(tsc --noEmit)
npm test # 自动化测试(node:test,夹具来自 examples/)
npm run build # 构建 dist/
手动渲染单个 .vue 查看:
node -e "import('fs').then(async fs => { const { compileVueToStaticHTML } = await import('./src/index.ts'); fs.writeFileSync('../output.html', await compileVueToStaticHTML('examples/Showcase.vue')) })"
源码为 TypeScript:开发时由 Node 原生 type stripping 直接运行(Node >= 23.6,
import 需写显式 .ts 扩展名);发布产物为 dist/ 下编译后的纯 JS + .d.ts。
项目结构
vue3tohtml/
├── src/
│ ├── index.ts # API 入口
│ ├── compiler.ts # SFC 编译(ssrRender + 样式)
│ └── ssr.ts # 组件求值 + renderToString + 缓存 + HTML 组装
├── test/
│ └── ssr.test.ts # 自动化测试
├── docs/
│ ├── architecture.html # 交互版架构图(主题切换 + 导出)
│ └── architecture.svg # README 内嵌用双主题架构图
├── examples/ # 测试夹具 + 示例组件
│ ├── Showcase.vue # 展示页(全特性试金石)
│ ├── TodoApp.vue # v-for / v-model / computed
│ ├── App.vue # TypeScript + scoped
│ ├── Simple.vue # 基础组件
│ └── TemplateOnly.vue # 无 script 块
└── tsconfig.json
许可证
MIT
Related Packages
Version History
| Version | Released | Vue | License |
|---|---|---|---|
| 1.2.0 | ^3.5.43 | MIT | |
| 1.1.0 | ^3.5.43 | MIT | |
| 1.0.0 | ^3.5.43 | MIT |