Home > Blockchain >  Dynamic import of component does not work with component path from variable
Dynamic import of component does not work with component path from variable

Time:07-04

Stack

  • Vue 3.2
  • Nuxt 3.0.0-rc.4
  • Vite 2.9

Goal

Trying to dynamically load a component with <component :is /> from a variable instead of a static string.

Code

Here is a minified example of what I am trying to achieve:

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

  const filepathStatic = '../foobar/Foobar.vue'

  const bar = 'bar'
  const filepathDynamic = `../foobar/Foo${bar}.vue` // meets all requirements

  const asyncComponent = defineAsyncComponent(() => {
    return import('../foobar/Foobar.vue') // WORKS
    
    return import(filepathStatic) // does NOT work
    return import(filepathDynamic) // does NOT work
  })
</script>

<template>
  <div>
    <component :is="asyncComponent" />
  </div>
</template>

Errors

1.) Vite-Error

The above dynamic import cannot be analyzed by vite.

See https://github.com/rollup/plugins/tree/master/packages/dynamic-import-vars#limitations for supported dynamic import formats. If this is intended to be left as-is, you can use the /* @vite-ignore */ comment inside the import() call to suppress this warning.

=> The dynamic filenames meet ALL the requirements stated on this page.

2.) Nuxt-Error

500
Cannot read properties of undefined (reading 'stubModule')

at __instantiateModule__ (./.nuxt/dist/server/server.mjs:4094:11)
at __ssrLoadModule__ (./.nuxt/dist/server/server.mjs:4085:25)
at ssrImport (./.nuxt/dist/server/server.mjs:4110:13)
at ssrDynamicImport (./.nuxt/dist/server/server.mjs:4121:12)
at ./.nuxt/dist/server/server.mjs:2808:14
at load (/node_modules/.pnpm/@vue [email protected]/node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:2255:17)
at setup (/node_modules/.pnpm/@vue [email protected]/node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:2308:24)
at callWithErrorHandling (/node_modules/.pnpm/@vue [email protected]/node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:157:22)
at setupStatefulComponent (/node_modules/.pnpm/@vue [email protected]/node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:7084:29)
at setupComponent (/node_modules/.pnpm/@vue [email protected]/node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:7039:11)

=> I have NO idea, why this does not work.

CodePudding user response:

The solution

I found the solution in the Nuxt documentation: https://v3.nuxtjs.org/guide/directory-structure/components/#dynamic-components

1.) locally (recommended)

If you want to use the Vue syntax, then you will need to use the resolveComponent helper provided by Vue.

2.) globally (not recommended)

Alternatively, though not recommended, you can register all your components globally, which will create async chunks for all your components and make them available throughout your application.

CodePudding user response:

This is how most tools do dynamic imports (be it Webpack, Vite, Rollup)

  1. Tool needs to know the used module (JS/TS file) at build time
  2. Providing only variable the tool does no nothing (it does not run your code to find out what can be it's value at runtime)

See this part of the docs of Rollup's dynamic-import-vars plugin used in the Vite

When a dynamic import contains a concatenated string, the variables of the string are replaced with a glob pattern. This glob pattern is evaluated during the build, and any files found are added to the rollup bundle. At runtime, the correct import is returned for the full concatenated string.

To know what to inject in the rollup bundle, we have to be able to do some static analysis on the code and make some assumptions about the possible imports. For example, if you use just a variable you could in theory import anything from your entire file system.

This means:

return import('../foobar/Foobar.vue') // works
    
return import(someVariable) // does NOT work

return import(`../foobar/${someVariable}.vue`) // works
  • Related