Vue3+Express SSR项目集成@vueuse/head及第三方插件问题咨询
问题解决方案
1 修复 useHead is not defined 报错
你猜测的原因是对的,该报错就是因为服务端入口没有注册@vueuse/head插件导致的。注意SSR场景下所有第三方插件都需要遵循「每次请求创建新实例」的原则,避免跨请求状态污染。
1.1 修改服务端入口文件
// main.server.js import { createApp } from 'vue' import App from './App.vue' import { createHead } from '@vueuse/head' // 若使用vue-router,在此导入路由创建函数 // import createRouter from './router' export function createServerApp() { const app = createApp(App) // 服务端每次请求创建独立的head实例 const head = createHead() app.use(head) // 注册vue-router逻辑和head一致,每次创建新实例再注册 // const router = createRouter() // app.use(router) return { app, head /* , router */ } }
1.2 补充服务端渲染逻辑中的head注入
在Node服务的渲染逻辑中,应用渲染完成后需要主动调用head的SSR渲染方法,把生成的元数据注入到HTML模板的head区域:
// 服务端渲染核心逻辑示例 import { renderToString } from 'vue/server-renderer' import { createServerApp } from './main.server.js' async function render(req, res) { const { app, head } = createServerApp() const appHtml = await renderToString(app) // 生成head标签内容 const { headTags, htmlAttrs, bodyAttrs } = head.renderSSR() // 把headTags、appHtml等内容插入到HTML模板中返回即可 const html = ` <!DOCTYPE html> <html ${htmlAttrs}> <head> ${headTags} </head> <body ${bodyAttrs}> <div id="app">${appHtml}</div> <script src="/client-bundle.js"></script> </body> </html> ` res.end(html) }
2 修复组件内CSS未被服务端正确编译问题
根据使用的构建工具不同,处理方案有区别:
- 如果用Vite构建:
- 开发环境下通过
vite.ssrLoadModule加载服务端入口时,Vite会自动收集组件内CSS,只需要把收集到的CSS注入到HTML的style标签中即可 - 生产环境构建时,先构建客户端bundle生成
manifest.json,服务端渲染时通过manifest查找对应组件的CSS资源,插入到HTML的link标签中
- 开发环境下通过
- 如果用Webpack构建:
- 服务端构建配置中开启vue-loader的SSR模式,同时使用
mini-css-extract-plugin提取CSS,或者通过vue-server-renderer的客户端资源清单自动注入CSS资源
- 服务端构建配置中开启vue-loader的SSR模式,同时使用
3 可选替代方案
如果需要更完善的SSR元数据支持,可以换用unhead,它是@vueuse/head的底层实现,API完全兼容,SSR相关文档更清晰,对Open Graph、Twitter Card等社交元数据的封装也更完善。
内容的提问来源于stack exchange,提问作者druj_nasu
相关产品推荐
相关产品推荐

