nuxt3如何去掉window.__NUXT__

1,816 阅读5分钟

1.前言

这两天朋友在群里问了这个问题,尝试过网上的方法,发现都没作用,于是研究花点时间研究了一会,终于把问题解决

项目环境

nuxt:3.0.0
node:16.15.0
vue:3.2.47
vite:3.2.5

2.说说网上的方案

vue-renderer:ssr:context

// Call ssr:context hook
await this.serverContext.nuxt.callHook('vue-renderer:ssr:context', renderContext)

以上代码是在nuxt 2.x源码,vue-renderer:ssr:context被触发时,返回一个渲染的上下文对象,通过此对象可以进行处理window._NUXT_

这也是在网上搜索得出的答案大部分指向这个,实际上在nuxt3此hooks已被删除,如果是nuxt 2.x版本可以利用此hooks去掉window._NUXT_,在此就不再列出具体示例代码

3.说说nuxt3的hooks

nuxt3提供了三类hooks分别是

App Hooks (runtime)(应用运行时hooks)

hook名称参数环境描述
app:createdvueApp服务器和客户端创建初始实例时调用。vueApp
app:errorerr服务器和客户端发生致命错误时调用。
app:error:cleared{ redirect? }服务器和客户端发生致命错误时调用。
app:data:refreshkeys?服务器和客户端(内部)
vue:setup-服务器和客户端(内部)
vue:errorerr, target, info服务器和客户端当 vue 错误指向根组件时调用。了解更多信息.
app:renderedrenderContext服务器SSR 渲染完成后调用。
app:redirected-服务器在 SSR 重定向之前调用。
app:beforeMountvueApp客户在挂载应用之前调用,仅在客户端调用。
app:mountedvueApp客户在浏览器中初始化并挂载 Vue 应用时调用。
app:suspense:resolveappComponent客户挂载完成 调用
link:prefetchto客户当观察到 被预取时调用。<NuxtLink>
page:startpageComponent?客户调用挂起的事件。
page:finishpageComponent?客户调用加载完成的事件。
page:transition:finishpageComponent?客户页面过渡后事件。

Nuxt Hooks (build time)(构建时hooks)

hook名称参数描述
kit:compatibilitycompatibility, issues允许扩展兼容性检查。
readynuxt在Nuxt初始化后调用,当Nuxt实例准备好工作时。
closenuxt在 Nuxt 实例正常关闭时调用。
modules:before-在Nuxt初始化期间,在安装用户模块之前调用。
modules:done-在Nuxt初始化期间,安装用户模块后调用。
app:resolveapp解析实例后调用。app
app:templatesapp在生成过程中调用,以允许自定义、修改或将新文件添加到构建目录(虚拟或写入)。NuxtApp``.nuxt
app:templatesGeneratedapp在模板编译到虚拟文件系统(VFS)。
build:before-在Nuxt捆绑构建器之前调用。
build:done-在Nuxt捆绑包生成器完成后调用。
build:manifestmanifest在清单构建期间由 Vite 和 Webpack 调用。这允许自定义 Nitro 将用于在最终 HTML 中呈现和标记的清单。<script>``<link>
builder:generateAppoptions在生成应用之前调用。
builder:watchevent, path在开发中的生成时,当观察程序发现对项目中的文件或目录的更改时调用。
pages:extendpages解析页面路由后调用。
server:devHandlerhandler在 Nitro 开发服务器上注册开发中间件时调用。
imports:sourcespresets在设置时调用,允许模块扩展源。
imports:extendimports在安装程序时调用,允许模块扩展导入。
imports:contextcontext调用时取消导入创建上下文。
imports:dirsdirs允许扩展导入目录。
components:dirsdirs在允许内调用,以扩展扫描的目录以查找可自动导入的组件。app:resolve
components:extendcomponents允许扩展新组件。
nitro:confignitroConfig在初始化 Nitro 之前调用,允许自定义 Nitro 的配置。
nitro:initnitro在 Nitro 初始化后调用,这允许注册 Nitro 钩子并直接与 Nitro 交互。
nitro:build:beforenitro在构建 Nitro 实例之前调用。
prerender:routesctx允许扩展要预渲染的路由。
build:errorerror在生成时发生错误时调用。
prepare:typesoptions在 Nuxi 编写 和 之前调用,允许在 中添加自定义引用和声明,或直接修改 中的选项.nuxt/tsconfig.json``.nuxt/nuxt.d.ts``nuxt.d.ts``tsconfig.json
listenlistenerServer, listener在加载开发服务器时调用。
schema:extendschemas允许扩展默认架构。
schema:resolvedschema允许扩展解析的架构。
schema:beforeWriteschema在编写给定架构之前调用。
schema:written-在写入架构后调用。
vite:extendviteBuildContext允许扩展 Vite 默认上下文。
vite:extendConfigviteInlineConfig, env允许扩展 Vite 默认配置。
vite:serverCreatedviteServer, env创建 Vite 服务器时调用。
vite:compiled-在编译 Vite 服务器后调用。
webpack:configwebpackConfigs在配置 webpack 编译器之前调用。
webpack:compileoptions在编译之前调用。
webpack:compiledoptions加载资源后调用。
webpack:changeshortPath在Webpack上调用。change
webpack:error-如果 Webpack 上有错误,则调用。done
webpack:done-在Webpack上调用。allDone
webpack:progressstatesArray在Webpack上调用。progress

Nitro App Hooks (runtime, server-side)(Nitro运行时,服务端)

参数描述类型
render:responseresponse, { event }在发送响应之前调用。响应,事件
render:htmlhtml, { event }在构造 HTML 之前调用。.html,事件

3.解决方案

本次nuxt3借助Nitro App Hooksrender:html拿到预渲染的htmlContext,进一步处理达到完整去掉window.__NUXT__

最佳实践

在项目根目录创建server文件夹,在server文件夹下创建plugins文件夹,在plugins文件下创建nitroPlugin.ts

export default defineNitroPlugin((nitroApp: { hooks: { hook: (arg0: string, arg1: (html: { bodyAppend: string[] }, { event }: any) => void) => void } }) => {
  nitroApp.hooks.hook('render:html', (html: { bodyAppend: string[] }, { event }: any) => {
    let index = html.bodyAppend.findIndex(i => i.indexOf('window.__NUXT__') != -1 )
    if(index != -1){
      html.bodyAppend.splice(index,1)
    }
  })
})

render:html会返回什么

通过render:html拿到的是什么数据结构,通过源码发现 返回了htmlContext(详细看下图),此htmlContext包含了整个首页的渲染数据,以及各种css,js的引用,window.__NUXT__ 就在bodyAppend字段中,bodyAppend会存在多个script,通过上述代码进行遍历查找bodyAppend确定window.__NUXT__ 的位置,进而进行删除 image.png