如何在Nuxt3中渲染Quarto静态HTML并实现用户认证?
核心问题在于public目录下的资源会被Nuxt直接作为静态文件服务,不经过Nuxt的路由系统和中间件拦截,所以要让认证生效,必须把Quarto页面纳入Nuxt的路由或服务端处理流程中。以下是三种可行方案:
方案1:用Nuxt页面承载Quarto HTML(推荐)
将Quarto生成的HTML文件移出public目录,通过Nuxt的动态页面+API接口加载内容,让请求走Nuxt路由体系,从而触发认证中间件。
步骤1:存放Quarto文件
把Quarto生成的所有HTML文件放到项目根目录的content/quarto文件夹(不要放public)。
步骤2:创建服务端API读取HTML
新建server/api/quarto/[slug].ts,用于根据文件名返回对应的HTML内容:
import { readFileSync } from 'fs' import { join } from 'path' export default defineEventHandler((event) => { const slug = getRouterParam(event, 'slug') if (!slug) throw createError({ statusCode: 404, message: '页面不存在' }) const filePath = join(process.cwd(), 'content/quarto', `${slug}.html`) try { const htmlContent = readFileSync(filePath, 'utf-8') return htmlContent } catch (e) { throw createError({ statusCode: 404, message: '页面不存在' }) } })
步骤3:创建带认证的动态页面
新建pages/blog/[slug].vue,通过API获取HTML并渲染,同时绑定认证中间件:
<template> <!-- 用v-html渲染Quarto生成的HTML内容 --> <div v-html="htmlContent"></div> </template> <script setup> // 绑定你的认证中间件 definePageMeta({ middleware: 'auth' }) const route = useRoute() // 从API拉取对应页面的HTML const { data: htmlContent } = await useFetch(`/api/quarto/${route.params.slug}`) </script>
现在访问/blog/你的文件名时,会先触发认证中间件,通过后再加载并渲染Quarto页面。
方案2:用Server Middleware拦截请求
通过Nuxt的服务端中间件直接拦截Quarto页面的请求,先做认证校验,通过后再返回HTML文件。
步骤1:存放Quarto文件
将HTML文件放到static-quarto目录(非public)。
步骤2:编写认证中间件
新建server/middleware/quartoAuth.ts:
import { readFileSync } from 'fs' import { join } from 'path' export default function quartoAuth(req, res, next) { // 替换成你的认证逻辑:检查session、token等 const isAuthenticated = checkUserAuth(req) if (!isAuthenticated) { res.writeHead(302, { Location: '/login' }) res.end() return } // 解析请求路径,读取对应HTML文件 const fileName = req.url?.replace('/quarto/', '') || '' const filePath = join(process.cwd(), 'static-quarto', `${fileName}.html`) try { const html = readFileSync(filePath, 'utf-8') res.writeHead(200, { 'Content-Type': 'text/html' }) res.write(html) res.end() } catch (e) { res.writeHead(404, { 'Content-Type': 'text/plain' }) res.write('页面不存在') res.end() } }
步骤3:配置中间件
在nuxt.config.ts中注册该中间件:
export default defineNuxtConfig({ serverMiddleware: [ { path: '/quarto', handler: '~/server/middleware/quartoAuth.ts' } ] })
访问/quarto/你的文件名时,会先经过认证校验,通过后返回Quarto页面。
方案3:将Quarto转为Markdown用Nuxt Content管理
如果Quarto支持导出Markdown(执行quarto render 你的笔记本.ipynb --to markdown),可以把内容转为Markdown后放到content目录,用Nuxt Content来管理渲染,这种方式更贴合Nuxt生态,还能利用内容系统的搜索、目录等功能。
新建pages/blog/[...slug].vue:
<template> <ContentDoc /> </template> <script setup> definePageMeta({ middleware: 'auth' }) </script>
Nuxt Content会自动匹配content目录下的Markdown文件,认证中间件也会正常生效。
内容的提问来源于stack exchange,提问作者Prot2014

