You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Vue SSR场景下应在何处调用Vue.use(plugin)?附bootstrap-vue实例问题

解决SSR中bootstrap-vue导致的Hydration不匹配问题

这个警告的核心原因很明确:服务端渲染的DOM结构和客户端hydrate时生成的DOM结构不一致——你只在客户端的router.onReady()里调用Vue.use(BootstrapVue),导致服务端的Vue实例根本没加载bootstrap-vue插件:服务端渲染的是原生HTML结构,客户端却用bootstrap-vue的组件重新渲染了一遍,结构自然对不上。

下面给你一套具体的解决步骤:

1. 统一在共享入口初始化bootstrap-vue

不要只在客户端注册插件,要让服务端和客户端的Vue环境完全同步。建议创建一个共享的应用创建函数,让服务端和客户端入口都调用它,在这个函数里完成插件的全局注册。

举个实际的代码例子:
首先创建createApp.js(服务端和客户端共用的入口):

import Vue from 'vue'
import BootstrapVue from 'bootstrap-vue'
// 别忘了引入样式,服务端和客户端都需要
import 'bootstrap/dist/css/bootstrap.css'
import 'bootstrap-vue/dist/bootstrap-vue.css'
import App from './App.vue'
import router from './router'
import store from './store'

// 全局注册bootstrap-vue,服务端和客户端都会执行这一步
Vue.use(BootstrapVue)

export function createApp() {
  const app = new Vue({
    router,
    store,
    render: h => h(App)
  })
  return { app, router, store }
}

然后修改服务端入口entry-server.js:

import { createApp } from './createApp'

export default context => {
  return new Promise((resolve, reject) => {
    const { app, router } = createApp()
    router.push(context.url)
    
    router.onReady(() => {
      const matchedComponents = router.getMatchedComponents()
      if (!matchedComponents.length) {
        return reject({ code: 404 })
      }
      resolve(app)
    }, reject)
  })
}

再修改客户端入口entry-client.js:

import { createApp } from './createApp'

const { app, router } = createApp()
router.onReady(() => {
  app.$mount('#app')
})

这样一来,服务端和客户端的Vue实例都会加载bootstrap-vue插件,渲染出来的DOM结构就能保持一致了。

2. 排查依赖客户端API的组件

如果还是有警告,那可能是某些bootstrap-vue组件依赖了客户端的API(比如window、document),服务端渲染时无法正常生成对应的DOM。这种情况下,你可以用Vue的<client-only>标签包裹这些组件,让它们只在客户端渲染:

<template>
  <div>
    <!-- 服务端能正常渲染的组件 -->
    <b-card title="SSR友好组件"></b-card>
    <!-- 依赖客户端API的组件,只在客户端渲染 -->
    <client-only>
      <b-modal id="example-modal" title="客户端专属组件"></b-modal>
    </client-only>
  </div>
</template>

3. 检查其他导致DOM不匹配的因素

有时候问题不一定出在bootstrap-vue上,你可以排查一下自己的业务组件:

  • 有没有在服务端渲染时调用了客户端专属的API?比如在created钩子中使用window,这会导致服务端和客户端渲染的内容不一致。
  • 有没有条件渲染依赖客户端状态?比如根据localStorage的值显示不同内容,服务端没有localStorage,自然渲染结果不同。

这类问题的解决方法是:用process.client判断环境,或者把依赖客户端的逻辑放到mounted钩子中执行。

比如:

export default {
  data() {
    return {
      userTheme: 'light'
    }
  },
  mounted() {
    // 只在客户端获取localStorage的值
    if (process.client) {
      this.userTheme = localStorage.getItem('theme') || 'light'
    }
  }
}

内容的提问来源于stack exchange,提问作者Hans Knöchel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 03:57:13