3

I created a sample project to reproduce this issue: https://github.com/splanard/vue3-vite-web-components

I initialized a vue3 project using npm init vue@latest, as recommanded in the official documentation.

Then I installed Scale, a stencil-built web components library. (I have the exact same issue with the internal design system of my company, so I searched for public stencil-built libraries to reproduce the issue.)

I configured the following in main.ts:

import '@telekom/scale-components-neutral/dist/scale-components/scale-components.css';
import { applyPolyfills, defineCustomElements } from '@telekom/scale-components-neutral/loader';

const app = createApp(App);
app.config.compilerOptions.isCustomElement = (tag) => tag.startsWith('scale-')

applyPolyfills().then(() => {
  defineCustomElements(window);
});

And the same isCustomElement function in vite.config.js:

export default defineConfig({
  plugins: [vue({
    template: {
      compilerOptions: {
        isCustomElement: (tag) => tag.startsWith('scale-')
      }
    }
  })]
  // ...
})

I inserted a simple button in my view (TestView.vue), then run npm run dev.

When opening my test page (/test) containing the web component, I have an error in my web browser's console:

failed to load module "http://localhost:3000/node_modules/.vite/deps/scale-button_14.entry.js?import" because of disallowed MIME type " "

As it's the case with both Scale and my company's design system, I'm pretty sure it's reproducible with any stencil-based components library.


Edit

It appears that node_modules/.vite is the directory where Vite's dependency pre-bundling feature caches things. And the script scale-button_14.entry.js the browser fails to load doesn't exist at all in node_modules/.vite/deps. So the issue might be linked to this "dependency pre-bundling" feature: somehow, could it not detect the components from the library loader?


Edit 2

I just found out there is an issue in Stencil repository mentioning that dynamic imports do not work with modern built tools like Vite. This issue has been closed 7 days ago (lucky me!), and version 2.16.0 of Stencil is supposed to fix this. We shall see.

For the time being, dropping the lazy loading and loading all the components at once through a plain old script tag in the HTML template seems to be an acceptable workaround.

<link rel="stylesheet" href="node_modules/@telekom/scale-components/dist/scale-components/scale-components.css">
<script type="module" src="node_modules/@telekom/scale-components/dist/scale-components/scale-components.esm.js"></script>

However, I can't get vite pre-bundling feature to ignore these imports. I configured optimizeDeps.exclude in vite.config.js but I still get massive warnings from vite when I run npm run dev:

export default defineConfig({
  optimizeDeps: {
    exclude: [
      // I tried pretty much everything here: no way to force vite pre-bundling to ignore it...
      'scale-components-neutral'
      '@telekom/scale-components-neutral'
      '@telekom/scale-components-neutral/**/*'
      '@telekom/scale-components-neutral/**/*.js'
      'node_modules/@telekom/scale-components-neutral/**/*.js'
    ],
  },
  // ...
});

Eria
  • 2,653
  • 6
  • 29
  • 56
  • I tested [your project on stackblitz](https://stackblitz.com/github/splanard/vue3-vite-web-components?file=index.html). Seem like the error has gone – Duannx Jun 23 '22 at 02:53
  • I don't know how stackblitz works but the error is still very much present. – Eria Jun 24 '22 at 13:46

2 Answers2

3

This issue has been fixed by Stencil in version 2.16.

Upgrading Stencil to 2.16.1 in the components library dependency and rebuilding it with the experimentalImportInjection flag solved the problem.

Then, I can import it following the official documentation:

main.ts

import '@telekom/scale-components-neutral/dist/scale-components/scale-components.css';
import { applyPolyfills, defineCustomElements } from '@telekom/scale-components-neutral/loader';

const app = createApp(App);

applyPolyfills().then(() => {
  defineCustomElements(window);
});

And configure the custom elements in vite config:

vite.config.js

export default defineConfig({
  plugins: [vue({
    template: {
      compilerOptions: {
        isCustomElement: (tag) => tag.startsWith('scale-')
      }
    }
  })]
  // ...
})
Eria
  • 2,653
  • 6
  • 29
  • 56
0

I did not configure main.ts

stencil.js version is 2.12.1,tsconfig.json add new config option in stencil:

{
  "compilerOptions": {
    ...
    "skipLibCheck": true,
    ...
  }
}

add new config option in webpack.config.js : vue 3 document

...
module: {
  rules:[
    ...
    {
      test: /\.vue$/,
      use: {
        loader: "vue-loader",
        options: {
          compilerOptions: {
            isCustomElement: tag => tag.includes("-")
          }
        }
      }
    }
    ...
  ]
}
...
jiujiu
  • 61
  • 1
  • 4