0

I have vue3+vite+quasar project with pages, components, etc. and I want individual components to be able to be turned into web components so that they can be used in any other places, I already had a little experience with this but now because of third-party libraries I have problems that I can't solve if you can help please

vite.config.ts

import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
import { quasar } from '@quasar/vite-plugin';

export default defineConfig({
  plugins: [
    vue(),
    quasar({
      autoImportComponentCase: 'pascal',
    }),
  ],
  define: {
    'process.env': {},
  },
  build: {
    target: 'esnext',
    rollupOptions: {
      output: {
        globals: {
          vue: 'Vue',
          quasar: 'Quasar',
        },
        assetFileNames: (assetInfo) => {
          if (assetInfo.name.endsWith('.css')) {
            return 'web.css';
          }
          return 'assets/[name]-[hash][extname]';
        },
        format: 'es',
        manualChunks: null,
        inlineDynamicImports: true,
      },
      external: [],
    },
    lib: {
      entry: 'src/main.ts',
      name: 'web',
      fileName: (format) => `web.${format}.js`,
      formats: ['es', 'umd', 'iife'],
    },
  },
});

main.ts

import 'quasar/dist/quasar.css';
import { createApp, defineCustomElement } from 'vue';
import { Quasar, QCard } from 'quasar';
import HelloWorld from './components/HelloWorld.vue';

const app = createApp(HelloWorld);

app.use(Quasar, {
    config: {
        dark: false,
    },
    components: {
        QCard,
    },
    plugins: [],
});

const createInstantGameElement = defineCustomElement(HelloWorld);

customElements.define('my-web-component', createInstantGameElement);


app.mount('#app');

HelloWorld.vue

<script setup lang="ts">
import { QCard } from 'quasar'
</script>

<template>
  test1
  <QCard class="q-pa-lg">
    test2
  </QCard>
</template>

<style scoped>

</style>

Try index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" href="../dist/web.css">
    <script type="module" src="../dist/web.es.js"></script>
</head>
<body>
<my-web-component/>
</body>
</html>

at the exit I see string 'test1' and warn with error [Vue warn]: Unhandled error during execution of render function at <QCard class="q-pa-lg" > at <VueElement >

and Uncaught TypeError: Cannot read properties of undefined (reading 'dark')

1 Answer 1

0

app.use(Quasar) can't affect Quasar components, while they are expected to rely on framework-specific configuration. Web components are rendered in isolation from the rest of Vue application, even if they are implemented with Vue components. The documentation mentions provide/inject, but this is a special case of the mentioned problem.

This requires to be aware of framework components in use and their implementation. It can be seen that QCard relies on $q global component property that is normally provided with app.use(Quasar) and uses props as a fallback.

So it could be fixed with:

...
<QCard class="q-pa-lg" :dark="false">
...

Or by installing Quasar plugin to application instance that web component uses with configureApp option:

defineCustomElement(HelloWorld, {
  configureApp(app) {
    app.use(Quasar, {
      config: {
        dark: false,
      }
    });
  },
});

No components is necessary because QCard is imported locally. app.use(Quasar) for main application instance isn't needed.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.