完全指南:使用 `usePreviewMode` 安全预览未发布的站点内容)
Nuxt 预览模式Preview Mode完全指南使用usePreviewMode安全预览未发布的站点内容【免费下载链接】nuxtthe full-stack Vue framework项目地址: https://gitcode.com/GitHub_Trending/nu/nuxtusePreviewMode是 Nuxt 3.11 内置的预览模式组合式函数它让站点可以在不向普通用户公开的前提下预览即将上线的内容变更开发者只需在 URL 上携带?previewtrue查询参数即可在已经构建部署的站点上以实时渲染的方式预览草稿、审核状态的内容并通过预置的数据刷新逻辑确保预览内容始终来自服务器端最新数据。读完本文你将掌握如何用usePreviewMode的四个核心选项shouldEnable、getState、onEnable、onDisable定制预览开关、预览状态与回调并能在本地通过nuxt generatenuxt preview完整走通预览流程。预览模式解决什么问题在内容型站点如 CMS、文档站、电商后台中编辑通常希望在正式发布前先看到真实站点上的效果。一种粗暴做法是直接在线上渲染草稿但这会泄露给所有访客另一种做法是开一套预发布环境成本高且与线上不一致。Nuxt 的预览模式给出的方案是在同一个已构建的站点上通过 URL 查询参数临时开启预览视角。站点本身照常生成与部署只有当请求携带特定参数时应用才会以预览状态运行显示草稿内容、携带预览 token 调用接口、并在状态变化时强制刷新页面数据。官方文档对预览模式的定位很简洁Preview mode allows you to see how your changes would be displayed on a live site without revealing them to users.预览模式让你可以在不向用户泄露的情况下查看变更在线上站点上会如何展示。其官方定义见 use-preview-mode 文档。核心 API启用与状态usePreviewMode在 组合式函数导出列表 中作为内置组合式函数对外公开自动导入无需手动 import并已登记在 导入预设因此在任何页面、组件或插件中都可以直接调用。调用后返回一个对象包含两个响应式引用const { enabled, state } usePreviewMode()enabled一个Refboolean表示当前是否处于预览模式且可写——直接赋值enabled.value false即可在运行时关闭预览下文示例会用到state预览模式的响应式状态对象默认用于存放 URL 中token参数的值可读写且在所有usePreviewMode调用之间共享因为它底层基于全局的useState实现。从源码 preview.ts 可以看到其内部实现首次调用时通过useStatePreview(_preview-state, () ({ enabled: false, state: {} }))创建一个名为_preview-state的全局状态随后把enabled、state以toRef的形式暴露。由于状态是全局的同一次页面会话中无论调用多少次usePreviewMode拿到的都是同一份数据。usePreviewMode会监测预览模式并自动处理数据刷新当检测到预览模式开启时它会强制触发useAsyncData与useFetch所需的更新从而重新渲染预览内容确保你看到的是服务器返回的最新数据而非脱水dehydrated的旧缓存。默认行为开箱即用的判定逻辑如果你不传入任何选项usePreviewMode会采用如下默认行为启用判定只有当 URL 中存在等于字符串true的preview查询参数时才启用例如http://localhost:3000?previewtrue。这一逻辑对应源码中的defaultShouldEnablepreview.tsfunction defaultShouldEnable (): boolean { const route useRoute() const previewQueryName preview return route.query[previewQueryName] true }默认状态尝试把 URL 中token查询参数的值存入state.token对应源码getDefaultStatepreview.ts。注意如果 URL 中token以数组形式存在多值查询参数则取第一个值若状态里已有token则不再覆盖function getDefaultState (state: Preview[state]): Preview[state] { if (state.token ! undefined) { return state } const route useRoute() state.token Array.isArray(route.query.token) ? route.query.token[0] : route.query.token return state }因此默认场景下http://localhost:3000?previewtruetokensecret-key会在开启预览的同时把state.token填充为secret-key供后续代码作为访问预览数据的凭据使用。一个值得注意的细节是在预渲染页面nuxt generate产物上真实路由及其查询参数要到水合hydration之后才会恢复。为此源码在客户端且尚未启用预览时会检查nuxtApp[~restoreDeferredRoute]并在app:suspense:resolve钩子触发时再次执行启用判定见 preview.ts 及对应 issue #35885 的修复逻辑这保证了基于 query 的预览判定在静态站点上依然可靠。选项一自定义启用条件shouldEnable默认的previewtrue判定可以完全替换。shouldEnable接收当前预览状态返回一个布尔值来决定是否启用预览模式export function useMyPreviewMode () { const route useRoute() return usePreviewMode({ shouldEnable: () { return !!route.query.customPreview }, }) }官方文档特别建议把usePreviewMode封装成自定义组合式函数如上例的useMyPreviewMode这样可以在整个应用的多次调用中保持选项一致并避免因各处传入不同选项而产生错误。仓库中 预览 fixture 页面 直接印证了这一用法script setup const route useRoute() const { enabled } usePreviewMode({ shouldEnable: () { return !!route.query.customPreview }, }) /script template div p idenabled{{ enabled }}/p /div /template对应的端到端测试test/e2e/preview.test.ts验证了两个方向访问/?previewtrue时enabled为false自定义判定取代了默认的preview参数访问/?customPreviewtrue时enabled才为true。这组用例很好地说明了shouldEnable是完全接管而非叠加默认逻辑。选项二修改默认状态getStategetState让你能在预览启用时注入自定义状态。它接收当前状态作为参数返回值会被合并进状态中const data1 ref(data1) const { enabled, state } usePreviewMode({ getState: (currentState) { return { data1, data2: data2 } }, })此后state.data1、state.data2在所有usePreviewMode调用中都可访问。由于返回值是合并append而非替换你也可以在这里动态追加与页面相关的预览数据。⚠️注意事项getState会把返回值追加到当前状态上因此要小心不要意外覆盖重要的既有状态例如默认写入的state.token。源码中对应的合并逻辑为Object.assign(preview.value.state, newState)见 preview.ts是浅合并而非整体替换。fixture 页面 with-custom-state.vue 演示了完整的联动效果页面初始化时把ref的data1值为data1与静态值data2: data2注入状态onMounted后把data1更新为data1 updated。测试断言test/e2e/preview.test.ts在?previewtrue下能读到data1 updated与data2——这说明注入状态的ref本身是响应式的状态内的值会跟随源ref一起更新。选项三自定义启停回调onEnable/onDisable预览模式的启停默认会联动全站数据刷新其默认策略如下启用时调用refreshNuxtData()立即从服务器重新拉取全部数据停用时注册一个afterEach路由钩子在下一次路由导航完成后再执行refreshNuxtData()。这两个默认行为均可在调用处替换为自定义回调const { enabled, state } usePreviewMode({ onEnable: () { console.log(preview mode has been enabled) }, onDisable: () { console.log(preview mode has been disabled) }, })结合源码看这一段的完整逻辑位于watch(preview.value.enabled, ...)中preview.ts预览开启时依次执行getState合并状态、调用options.onEnable ?? refreshNuxtData若未提供自定义onDisable则用useRouter().afterEach(() refreshNuxtData())注册卸载钩子并通过模块级变量unregisterRefreshHook保存待预览关闭时注销防止重复注册。理解默认数据刷新机制对排查问题很有帮助refreshNuxtData定义于 asyncData.ts其核心是触发app:data:refresh钩子支持按 key 定向刷新从而让useAsyncData/useFetch重新执行请求。这意味着进入预览→重取数据→展示最新内容与退出预览→下一次导航后重取数据→回到正式内容两套流程是开箱即用的。完整实战示例仅在预览模式渲染的内容下面这个页面中一部分内容只在预览模式下渲染。预览时向接口传入state.token作为apiKey页面内通过按钮可以随时关闭预览模式script setup const { enabled, state } usePreviewMode() const { data } await useFetch(/api/preview, { query: { apiKey: state.token, }, }) /script template div Some base content p v-ifenabled Only preview content: {{ state.token }} br button clickenabled false disable preview mode /button /p /div /template这段代码体现了预览模式的两个常见应用模式内容差异化渲染用v-ifenabled控制仅预览可见的 DOM 片段凭据透传把 URL 中token自动填充的state.token作为预览专用接口的鉴权参数使服务器可以据此区分返回草稿或正式内容。仓库中对应的完整可运行版本位于 fixture 目录 test/fixtures/preview/页面 with-use-fetch.vue 在useFetch中把apiKey设为state.token || undefined服务端 server/api/preview.ts 据此决定响应内容端到端测试test/e2e/preview.test.ts验证了携带?previewtruetokenhehe访问时能正确展示 token 并以apiKey命中预览响应同时确认水合后数据确实在客户端重新获取fetched on client出现证明预览开启时发生了客户端侧数据刷新。在本地走通完整的预览流程预览模式依赖构建后通过静态预览服务器访问这一场景请使用下面的命令序列验证npx nuxt generate npx nuxt preview然后打开你的页面并在 URL 末尾追加查询参数preview一次性即可看到预览效果例如http://localhost:3000/?previewtrue务必注意usePreviewMode应当配合nuxt generatenuxt preview在本地测试而不要用nuxt dev来测试。原因是预渲染/预览场景真实路由与 query 的恢复时机、客户端重新拉取数据的语义与开发服务器存在差异。另外官方文档特别提示preview命令用于本地预览构建产物与预览模式preview mode是两个不同的概念名称相近但互不相关。常见问题与最佳实践小结预览状态是全局共享的usePreviewMode基于_preview-state全局状态实现多个组件中解构出的state指向同一对象跨组件通信与数据同步无需额外状态管理。enabled是可写的需要手动退出预览时直接enabled.value false模板中即enabled false此时会触发onDisable或默认的下次导航后刷新数据逻辑页面随之回到正式内容。不要把关键状态冲掉getState返回的对象会被浅合并进现有状态应避免返回覆盖token等默认字段的同名属性。自定义判定要封装复用若要换用customPreview等自定义参数建议抽取为统一的组合式函数如useMyPreviewMode避免散落各处、选项不一致。静态站点上 query 判定是可靠的源码针对预渲染页面在水合后恢复路由的时序做了专门处理app:suspense:resolve后重新执行checkEnabled所以nuxt generate产物上基于 URL 参数开启预览的写法是安全的。预览模式把发布前的最后一轮核对从预发布环境搬回了线上站点本身配合usePreviewMode的四个选项你可以自由定制开启条件、预览状态与刷新时机在最小改动下构建一套符合自身内容审核流程的预览体验。延伸阅读与本 API 相关的数据刷新机制refreshNuxtData见 refresh-nuxt-data 文档被预览模式自动驱动的数据获取useAsyncData见 use-async-data 文档、useFetch见 use-fetch 文档全局状态基础useState见 use-state 文档实现源码preview.ts端到端测试与 fixturepreview.test.ts、preview fixture【免费下载链接】nuxtthe full-stack Vue framework项目地址: https://gitcode.com/GitHub_Trending/nu/nuxt创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考