Subscribe on changes!

<chess-board> web component does not load on Vue 3, works fine in Vue 2

avatar
May 15th 2022

Link to minimal reproduction

https://github.com/vesper8/chessboard-element-vue-cli-vue3-test

Steps to reproduce

I recently migrated a Vue 2 project to Vue 3 and I noticed that I have some serious issues with a web component.

I created three minimal reproduction repositories:

vue-cli + Vue 2: https://github.com/vesper8/chessboard-element-vue-cli-vue2-test vue-cli + Vue 3: https://github.com/vesper8/chessboard-element-vue-cli-vue3-test Vite + Vue 3: https://github.com/vesper8/chessboard-element-vite-vue3-test

The Vue 2 one just works perfectly, no issues whatsoever.

Both Vue 3 repos suffer from the exact same behaviour.

The custom web component is https://github.com/justinfagnani/chessboard-element

yarn add chessboard-element

As I mentioned, with Vue 2 is just works without a pinch.

With the two Vue 3 ones.. the web component will ONLY load IF the custom element is present BEFORE the call to import "chessboard-element";

As you can see in https://github.com/vesper8/chessboard-element-vite-vue3-test/blob/main/src/views/Page-1.vue, in this case the web component will get its styling, but will not fully initialize (show the chess pieces).

Whereas in https://github.com/vesper8/chessboard-element-vite-vue3-test/blob/main/src/views/Page-3.vue, through some hacky workaround, I first mount a template with the custom <chess-board /> element and then I load a child component ChessBoardLoader and I purposefully delay the loading of that child component with setTimeout to make sure it loads after, then it works. If you hit http://localhost:3000/page-3 and reload that page, the web component fully loads.

If however you move from Page 3 to any other Page, or from any other page to Page 3, then the web component fails to fully load.

I have no idea what to make of this.. but I'm really hoping someone can assist or propose a working solution even if it's hacky. Or at least explain why this is happening.

Furthermore, in the router configuration for both Vue 3 repos, if you try something like this:

  import Page1 from "@/views/Page-1.vue";
  import Page2 from "@/views/Page-2.vue";
  import Page3 from "@/views/Page-3.vue";
  import Page4 from "@/views/Page-4.vue";

  ...

  { path: "/page-1", component: Page1 },
  { path: "/page-2", component: Page2 },
  { path: "/page-3", component: Page3 },
  { path: "/page-4", component: Page4 },

Then hit http://localhost:3000/page-3, then it will fail, because the import "chessboard-element"; was "pre-loaded" and that's a deal breaker with Vue 3. So the only way to make Page3 work is by using dynamic imports like this:

  { path: "/page-1", component: () => import('./views/Page-1.vue') },
  { path: "/page-2", component: () => import('./views/Page-2.vue') },
  { path: "/page-3", component: () => import('./views/Page-3.vue') },
  { path: "/page-4", component: () => import('./views/Page-4.vue') },

Again, with Vue 2, this doesn't matter, it works with or without dynamic imports

What is expected?

Web components should load on every page like they do on Vue 2

What is actually happening?

Web component is not loading, or only loads under specific and unmanageable circumstances

System Info

No response

Any additional comments?

No response