vuejs / vitepress

Vite & Vue powered static site generator.
https://vitepress.dev
MIT License
13.11k stars 2.11k forks source link

Quasar and Vitepress: Cannot convert undefined or null to object #2298

Closed Salimify closed 1 year ago

Salimify commented 1 year ago

Describe the bug

While trying to run document some components built on top of Quasar components, I was unable to run vitepress build docs for my project and throwing error

✓ building client + server bundles... ✖ rendering pages... build error: TypeError: Cannot convert undefined or null to object at Function.assign () at installQuasar (......dist\quasar.cjs.prod.js:6:15454) at Object.install (......\quasar\dist\quasar.cjs.prod.js:6:491344) at Object.use (......\dist\runtime-core.cjs.prod.js:3350:28) at Object.enhanceApp (....../docs/.vitepress/.temp/app.js:5580:9) at createApp (....../docs/.vitepress/.temp/app.js:5881:17) at render (....../docs/.vitepress/.temp/app.js:5921:33) at renderPage (....../vitepress/dist/node/serve-c489c02c.js:41209:25) at ....../node_modules/vitepress/dist/node/serve-c489c02c.js:41742:21 at Array.map ()

Reproduction

config.ts

import { defineConfig } from 'vitepress'
import vueJsx from '@vitejs/plugin-vue-jsx'
import * as path from "path";

export default defineConfig(
    {
      lang: 'en-US',
      title: 'MyLib',
      lastUpdated: true,
      titleTemplate: false,
      themeConfig: {
        siteTitle: 'MyLib',
        docFooter: {
          prev: 'Prev',
          next: 'Next'
        },
      },
      vite: {
        plugins: [
          vueJsx(),
        ],
        resolve: {
            alias: [
                {find: "@", replacement: path.resolve(__dirname, '../../src') },
                {find: "components", replacement: path.resolve(__dirname, '../components') }
            ],
            dedupe: ['vue', 'quasar', 'Quasar', 'pubsub-js'],
        },
        build: {
            rollupOptions: {
                external: ['vue', /quasar\/.+/]
            }
        },
      }
    }
)

index.ts

import DefaultTheme from 'vitepress/theme'
import { App, onMounted } from 'vue'
import { dispatchEventStorage } from '../utils/tools'
import MyLib from 'my-lib '

import Container from "../components/Container.vue";
import {Quasar } from "quasar";
import {quasarConfig} from "@";

export default {
  ...DefaultTheme,
  enhanceApp ({ app }: { app: App }) {
    app.use(Quasar, {
      components: {
        ...quasarConfig.components,
      },
      directives: {
        ...quasarConfig.directives,
      },
      plugins: {
        ...quasarConfig.plugins,
      },
    });
    app.use(MyLib);
    app.component('Container', Container)
  },

  setup () {
    onMounted(() => {
      dispatchEventStorage()
    })
  }
}

Expected behavior

As vitepress dev docs works fine and serving the documentation with the required component example, running 'vitepress build docs' is not running fine in rendering pages step.

System Info

windows: 11,
node: v16.19.1
npm: 8.19.3
quasar: 2.10.2
vue: 3.2.47
vite: 4.3.1
vitepress: 1.0.0-alpha.73

Additional context

No response

Validations

brc-dd commented 1 year ago

Might need to add Quasar related things in vite.optimizeDeps.exclude or vite.ssr.noExternal. Can you share the code using https://vitepress.new, it'll be easier for us to quickly test things there.

Salimify commented 1 year ago

Might need to add Quasar related things in vite.optimizeDeps.exclude or vite.ssr.noExternal. Can you share the code using https://vitepress.new, it'll be easier for us to quickly test things there.

@brc-dd Issue reproduced on stackblitz , everything seems to be working fine when running vitepress dev docs, but it still breaks when running vitepress build docs. Both vite.optimizeDeps.exclude and vite.ssr.noExternal did not help.

brc-dd commented 1 year ago

Hey, tbh I have never used Quasar. So, are there any docs where they mention their vue plugin? My guess is it should have some special handling for SSR.

brc-dd commented 1 year ago

Okay, so I searched other issues on Quasar and found someone using it with VitePress (https://github.com/quasarframework/quasar/issues/15211). Here is what they are doing:

    app.use(Quasar, {}, { req: { headers: {} } });

https://stackblitz.com/edit/vite-acj5cz

It needs a third parameter called ssrContext ({ req: { headers: {} } } in this case). I can find it being referenced in Quasar's source code but I don't fully understand how it's working.

Edit: ah it looks like they are using the ssrContext for getting the user-agent from req headers and setting some cookies via response header, which might make sense in case of SSR but are safe to ignore in case of SSG (vitepress).

If you don't want to put that extra req thing there, consider creating a issue at Quasar's GitHub repo asking them to use optional chaining while accessing values from ssrContext.