【问题标题】:Vite JS / Vue 3 / SSR: ReferenceError window is not definedVite JS / Vue 3 / SSR:未定义 ReferenceError 窗口
【发布时间】:2021-08-11 02:17:42
【问题描述】:

我将 Vite JS 与 Vue 3 一起用于带有服务器端渲染的单页应用程序。

我知道只能在客户端执行的 JS 必须要水合,但是用包可以吗?

我的情况是我希望能够使用 Headless UI(用于 Tailwind UI),只要应用程序作为单页应用程序启动,它就可以正常工作。使用 SSR 启动时出现此错误:

[Vue warn]: Unhandled error during execution of setup function


at <Dialog as="div" static="" class="fixed z-10 inset-0 overflow-y-auto"  ... >
ReferenceError: window is not defined
    at useWindowEvent (C:\test\node_modules\.pnpm\@headlessui+vue@1.2.0_vue@3.0.11\node_modules\@headlessui\vue\dist\headlessui.cjs.development.js:408:3)
    at useFocusTrap (C:\test\node_modules\.pnpm\@headlessui+vue@1.2.0_vue@3.0.11\node_modules\@headlessui\vue\dist\headlessui.cjs.development.js:486:3)
    at setup (C:\test\node_modules\.pnpm\@headlessui+vue@1.2.0_vue@3.0.11\node_modules\@headlessui\vue\dist\headlessui.cjs.development.js:1052:5)
    at callWithErrorHandling (C:\test\node_modules\.pnpm\@vue+runtime-core@3.0.11\node_modules\@vue\runtime-core\dist\runtime-core.cjs.js:156:22)
    at setupStatefulComponent (C:\test\node_modules\.pnpm\@vue+runtime-core@3.0.11\node_modules\@vue\runtime-core\dist\runtime-core.cjs.js:6488:29)
    at setupComponent (C:\test\node_modules\.pnpm\@vue+runtime-core@3.0.11\node_modules\@vue\runtime-core\dist\runtime-core.cjs.js:6449:11)
    at renderComponentVNode (C:\test\node_modules\.pnpm\@vue+server-renderer@3.0.11_vue@3.0.11\node_modules\@vue\server-renderer\dist\server-renderer.cjs.js:160:17)
    at renderVNode (C:\test\node_modules\.pnpm\@vue+server-renderer@3.0.11_vue@3.0.11\node_modules\@vue\server-renderer\dist\server-renderer.cjs.js:263:22)
    at renderComponentSubTree (C:\test\node_modules\.pnpm\@vue+server-renderer@3.0.11_vue@3.0.11\node_modules\@vue\server-renderer\dist\server-renderer.cjs.js:228:13)
    at renderComponentVNode (C:\test\node_modules\.pnpm\@vue+server-renderer@3.0.11_vue@3.0.11\node_modules\@vue\server-renderer\dist\server-renderer.cjs.js:173:16)

我了解该错误是由于服务器端无法访问窗口属性,但这是由程序包本身设置的。

有没有办法告诉 Vite JS SSR 不要在那个包上执行 JS,除非它在客户端?

这是导致错误的 vue 组件的内容(仅在 SSR 执行时,Dialog 来自 Headless UI):

<template>
  <TransitionRoot as="template" :show="open">
    <Dialog as="div" static class="fixed z-10 inset-0 overflow-y-auto" @close="open = false" :open="open">
      <div class="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0">
        TEST
      </div>
    </Dialog>
  </TransitionRoot>
</template>

<script>
import { ref } from 'vue'
import { Dialog, TransitionRoot } from '@headlessui/vue'

export default {
  components: {
    Dialog,
    TransitionRoot
  },
  setup() {
    const open = ref(true)

    return {
      open,
    }
  },
}
</script>

PS:如果您需要配置参考,我使用了这个样板项目:https://github.com/frandiox/vitesse-ssr-template

【问题讨论】:

    标签: vue.js server-side-rendering vite


    【解决方案1】:

    我在 Vue2 中遇到过类似的问题 我实际上是在尝试使用 apexchart,在构建之后,我得到了Reference error window is not defined 我所做的是我安装了 vue-client-only 然后在我的入口文件中添加了

    if (typeof window !== 'undefined') {
        const VueApexCharts = require('vue-apexcharts')
        Vue.component('ApexChart', VueApexCharts)
      }
    

    我用组件包装了它

    <template>
        <client-only>
                    <div id="chart">
                      <apex-chart type="radar" height="350" :options="chartOptions" :series="series"></apex-chart>
                    </div>
        </client-only>
    </template>
    <script>
    import ClientOnly from 'vue-apexcharts'
    export default {
      components: {
    ClientOnly
    }}
    </script>
    

    【讨论】:

      【解决方案2】:

      您应该仅在客户端导入和使用该包。

      对于仅在客户端导入,您可以使用 require 而不是这样的导入:

      let headlessui
      if (process.browser) headlessui= require('@headlessui/vue')
      

      然后在您的模板中,您可以将所有客户端组件放在&lt;client-only&gt;&lt;/client-only&gt; 标签中:

      <client-only>
          <TransitionRoot as="template" :show="open">
              <Dialog as="div" static class="fixed z-10 inset-0 overflow-y-auto" @close="open = false" :open="open">
                <div class="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text- center sm:block sm:p-0">
                  TEST
                </div>
              </Dialog>
           </TransitionRoot>
      <client-only>
      

      【讨论】:

      • 但这意味着我根本无法在 SSR 上使用这些组件,对吧?比如,我希望它们仍然显示在 SSR 上,只是不执行 JS,除非在客户端?
      • 你不能分离组件的js和模板。他们一起工作。检查哪些组件只能在客户端执行,并且只将它们放在仅限客户端的标签中。其他组件仍然可以在服务器端渲染
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-03-30
      • 2020-10-08
      • 2018-05-27
      • 2020-09-18
      • 1970-01-01
      相关资源
      最近更新 更多