question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

vue: dynamic component imports are not resolved

See original GitHub issue

Describe the bug

With Vue, you can define async components with a dynamic import like the following:

<template>
  <button @click="showHello = true">Show Hello</button>
  <div v-if="showHello">
    <div>Async component</div>
    <Hello :count="1"></Hello>
  </div>
</template>

<script setup lang="ts">
import { defineAsyncComponent, ref } from 'vue';

const Hello = defineAsyncComponent(() => import('./Hello.vue'));
const showHello = ref(false);
</script>

Hello.vue is then loaded only when the user clicks on the button Show Hello

But a unit test checking this behavior fails with Vitest:

import { mount, flushPromises } from '@vue/test-utils';
import AsyncComp from '../components/AsyncComp.vue';

test('mount component', async () => {
  const wrapper = mount(AsyncComp);

  expect(wrapper.text()).toContain('Show Hello');

  await wrapper.get('button').trigger('click');
  expect(wrapper.vm.showHello).toBe(true);
  await flushPromises();
  // I suppose this should work but does not
  expect(wrapper.text()).toContain('1 x 2');
});

Maybe I’m missing something obvious in the test setup, but it looks like the promise is never resolved.

Reproduction

https://stackblitz.com/edit/vitest-dev-vitest-bmfn8b

System Info

System:
    OS: macOS 12.3.1
    CPU: (10) arm64 Apple M1 Max
    Memory: 16.90 GB / 64.00 GB
    Shell: 5.8 - /bin/zsh
  Binaries:
    Node: 16.15.0 - ~/.volta/tools/image/node/16.15.0/bin/node
    Yarn: 1.22.17 - ~/.volta/tools/image/yarn/1.22.17/bin/yarn
    npm: 6.14.17 - ~/.volta/tools/image/npm/6.14.17/bin/npm
  Browsers:
    Chrome: 101.0.4951.64
    Firefox: 100.0
    Safari: 15.4
  npmPackages:
    @vitejs/plugin-vue: 2.3.3 => 2.3.3
    vite: 2.9.9 => 2.9.9
    vitest: 0.12.6 => 0.12.6

Used Package Manager

yarn

Validations

Issue Analytics

  • State:closed
  • Created a year ago
  • Reactions:1
  • Comments:14 (9 by maintainers)

github_iconTop GitHub Comments

2reactions
cexbrayatcommented, May 23, 2022

Yeah, I think we can either offer a wrapper in VTU, or at least document how to build it once a utility is available 👍

1reaction
sheremet-vacommented, May 21, 2022

I found a way to load it, using Vitest internals:

  await flushPromises() // this is needed for vue to start importing
  const worker = globalThis.__vitest_worker__
  const promises = [...worker.moduleCache.values()]
    .filter(m => !m.exports && m.promise)
    .map(m => m.promise)
  await Promise.all(promises) // this is needed for us to wait until module is loaded
  await flushPromises() // this is needed for vue to rerender component

To break it down,

  1. We clicked “Show Hello”
  2. Vue initiated loading, but haven’t called loader yet
  3. We are waiting until the end of the even loop, because Vitest haven’t started importing yet
  4. When Vitest imports modules it puts it inside moduleCache, so we can use it to guarantee that module is loaded
  5. We need to wait until the end of the event loop for Vue to rerender component

I found a bug that Vitest stores some modules twice, but it is out of scope of this issue. I am not sure what else I can do to help you, @cexbrayat

Read more comments on GitHub >

github_iconTop Results From Across the Web

Vue 2 dynamic component import issue
It looks like Vue.prototype.$VUE_LOADER_CONFIG.componentUrl contains a relative path. Try to use an absolute path instead: Vue.prototype.
Read more >
Component Registration | Vue.js
A Vue component needs to be "registered" so that Vue knows where to locate its implementation when it is encountered in a template....
Read more >
Lazy Loading Routes
Do not use Async components for routes. Async components can still be used inside route components but route component themselves are just dynamic...
Read more >
Components Basics
When not using a build step, a Vue component can be defined as a plain ... To expose the imported component to our...
Read more >
A Vue pattern for idiomatic, performant component ...
Notice how we avoided importing and registering the components because our dynamic import is doing so at runtime ❤ . There's more information...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found