javascriptvue.jsvitecustom-elementlit

How to make Vue and Vite work with web components?


I want to migrate my Vue 2 project from webpack to Vite. And have to use 3rd party web components that built with lit-element.

Those components throws errors during the runtime (by vue):

Unknown custom element: < foo-component > - did you register the component correctly? For recursive components, make sure to provide the "name" option.

And also (by lit-element)

Failed to set the 'adoptedStyleSheets' property on 'ShadowRoot': Failed to convert value to 'CSSStyleSheet'.

As far as I can see those 3rd party web components do only this in theirs index files (inside node_modules):

import FooComponent from './FooComponent';
customElements.define('foo-component', FooComponent);

So before (with webpack setup) I just imported them and everything used to work. Well, actually for webpack lit-scss-loader was used also for those components.

I assume that Vite perhaps needs some additional configuration, or maybe something similar to "webpack" loader is needed here, but not sure what direction I have to move.

What I'm doing wrong?


Solution

  • A couple of steps are needed.

    Imagine I have 3rd party webcomponents named "foo". So all of them are in node_modules/@foo.

    I need to do these steps:

    1. Tell Vite that all components starting with "foo-" are webcomponents.

      isCustomElement: (tag) => tag.startsWith('foo-')

    2. Add the "postcssLit" plugin to help vite prepare the CSS for the webcomponents.

    3. Tell Vite how to treat CSS paths for webcomponents.

      '~@foo': fileURLToPath(new URL('./node_modules/@foo', import.meta.url))

    Here is the full config:

    //vite.config.ts
    
    import postcssLit from 'rollup-plugin-postcss-lit';
    
    export default defineConfig({
      plugins: [
        vue(
          {
            template: {
              compilerOptions: {
                // 1. Tell Vite that all components starting with "foo-" are webcomponents
                isCustomElement: (tag) => tag.startsWith('foo-')
              }
            }
          }
        ),
        vueJsx(),
        // 2. This "postcssLit" plugin helps prepare CSS for the webcomponents
        postcssLit()
      ],
      resolve: {
        alias: {
          // 3. Tell Vite how to treat CSS paths for webcomponents
          '~@foo': fileURLToPath(new URL('./node_modules/@foo', import.meta.url))
        }
      }
    });