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

如何在Laravel10+Inertia SSR中使用仅客户端Vue插件?

解决Laravel 10 + Jetstream + Inertia SSR下Vue Apexcharts与@fawmi/vue-google-maps的兼容问题

这两个插件故障的核心原因是:它们都依赖浏览器环境的API(如window、document),而SSR在服务端渲染阶段不存在这些对象,直接引入会触发环境不兼容报错。以下是针对性的解决方法:

一、处理Vue Apexcharts

方案1:动态导入+客户端专属渲染

通过client-only组件确保服务端跳过渲染,仅在客户端动态加载组件与依赖资源:

<template>
  <client-only>
    <apexchart 
      v-if="ApexChart" 
      :options="chartOptions" 
      :series="series" 
      type="bar" 
      height="350" 
    />
  </client-only>
</template>

<script setup>
import { ref, onMounted } from 'vue'
import { useHead } from '@inertiajs/vue3'

const ApexChart = ref(null)
const chartOptions = ref({
  // 你的图表配置项
  xaxis: { categories: ['Jan', 'Feb', 'Mar'] }
})
const series = ref([{ name: 'Sales', data: [30, 40, 45] }])

onMounted(async () => {
  // 仅在客户端导入组件
  const module = await import('vue3-apexcharts')
  ApexChart.value = module.default
})

// 客户端加载Apexcharts的CSS与脚本
useHead({
  script: [{ src: 'https://cdn.jsdelivr.net/npm/apexcharts', body: true, async: true }],
  link: [{ rel: 'stylesheet', href: 'https://cdn.jsdelivr.net/npm/apexcharts/dist/apexcharts.css' }]
})
</script>

方案2:拆分插件注册逻辑

在客户端入口resources/js/app.js中注册Apexcharts,服务端入口resources/js/ssr.js中跳过注册:

// app.js(仅客户端)
import { createApp, h } from 'vue'
import { createInertiaApp } from '@inertiajs/vue3'
import ApexCharts from 'vue3-apexcharts'

createInertiaApp({
  resolve: name => require(`./Pages/${name}.vue`),
  setup({ el, App, props, plugin }) {
    return createApp({ render: () => h(App, props) })
      .use(plugin)
      .use(ApexCharts)
      .mount(el)
  },
})

ssr.js中不要添加use(ApexCharts)的代码,避免服务端打包时引入插件。

二、处理@fawmi/vue-google-maps

方案1:动态导入+客户端渲染

同样用client-only隔离服务端渲染,动态加载组件与Google Maps脚本:

<template>
  <client-only>
    <GMapMap
      v-if="GMapMap"
      :center="{ lat: 51.093048, lng: 6.842120 }"
      :zoom="10"
      style="width: 100%; height: 400px"
    >
      <GMapMarker :position="{ lat: 51.093048, lng: 6.842120 }" />
    </GMapMap>
  </client-only>
</template>

<script setup>
import { ref, onMounted } from 'vue'
import { useHead } from '@inertiajs/vue3'

const GMapMap = ref(null)
const GMapMarker = ref(null)

onMounted(async () => {
  const module = await import('@fawmi/vue-google-maps')
  GMapMap.value = module.GMapMap
  GMapMarker.value = module.GMapMarker
})

// 客户端加载Google Maps官方脚本(替换为你的API密钥)
useHead({
  script: [{ 
    src: `https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&libraries=places`, 
    body: true, 
    async: true 
  }]
})
</script>

方案2:拆分插件注册逻辑

仅在客户端入口注册Google Maps插件:

// app.js(仅客户端)
import { createApp, h } from 'vue'
import { createInertiaApp } from '@inertiajs/vue3'
import VueGoogleMaps from '@fawmi/vue-google-maps'

createInertiaApp({
  resolve: name => require(`./Pages/${name}.vue`),
  setup({ el, App, props, plugin }) {
    return createApp({ render: () => h(App, props) })
      .use(plugin)
      .use(VueGoogleMaps, {
        load: {
          key: 'YOUR_API_KEY',
          libraries: 'places',
        },
      })
      .mount(el)
  },
})

ssr.js中不要包含VueGoogleMaps的注册代码。

通用调试技巧

  1. 查看服务端日志,确认报错是否为window is not defined或浏览器API缺失类问题;
  2. 所有依赖浏览器环境的组件,都优先用client-only包裹或动态导入;
  3. 优先查阅插件官方文档,部分插件会提供SSR专属的兼容配置。

内容的提问来源于stack exchange,提问作者Andrii

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 13:29:57