#Are 'dynamic component imports' possible?

1 messages · Page 1 of 1 (latest)

floral haven
#

Hey all, I'm new to JS dev and looking for some help/guidence.

I have a file:

'@lib/componentMappingImports.astro'

which contains the following frontmatter:

---
import Component001 from '@components/Component001.astro';
import Component002 from '@components/Component002.astro';

export const componentMapping = {
    'Component001': Component001,
    'Component002': Component002,
};
---

If I manully update the imports and componentMapping object everything works as needed, but I was wondering if it is possible to 'dynamically' create both the imports and the componentMapping object using glob.

The following returns an array with he value of ['Component001', 'Component002']:

const getComponents = await Astro.glob('@components/**/*.astro');
let componentNames = getComponents.map((component: any) => component.file.split('/').pop().split('.').shift());

But this is where I'm stuck.

Any ideas if this is achievable?

Thanks for any guidence in advance.

floral haven
#

Are 'dynamic component imports' possible?

vagrant sigil
floral haven
# vagrant sigil Hey! `import.meta.glob` is probably what you want to use here https://vitejs.dev...

Thanks for the pointer, however shaping the object isn't the issue as I can do that with the following code:

  const getComponents =  await Astro.glob('@components/**/*.astro');
  const componentNames = getComponents.map((component: any) => component.file.split('/').pop().split('.').shift());

  const componentMapping = componentNames.reduce((acc: any, name: string) => {
    acc[name] = name;
    return acc;
  }, {});

The issue is Importing the components dynamically - once imported, I have the rest sorted with:

{components && components.map((component: string) => {
        const ComponentType = componentMapping[component.acf_fc_layout];
        if (ComponentType) {
            return (
                <ComponentType
                    {...component}
                />
            );
        } else {
            return null;
        }
      })}
vagrant sigil
#

You want to use dynamic import, as in importing components with the import function?
(e.g import(componentPath))

floral haven
vagrant sigil
#

It's possible, but there are limitations on what you can import (e.g import aliases aren't supported)

#

Ultimately, dynamic imports compile to glob imports, so manually using them is alright 😄

#

Did you have any concerns with using glob imports?

floral haven
jagged rock
#

You settled upon my exact solution but I have not found a way to dynamically import so I have all of the components in a file mapped to their ACF Flexible Content layouts like so:

import { default as Hero } from './Hero.astro'
import { default as HeroWithContent } from './HeroWithContent.astro'
import { default as HeroWithHeading } from './HeroWithHeading.astro'
import { default as HeroCarousel } from './HeroCarousel.astro'
import { default as HeroRandom } from './HeroRandom.astro'

export const flexibleContentComponents = {
  ModulesLayoutsHeroLayout: Hero,
  ModulesLayoutsHeroWithContentLayout: HeroWithContent,
  ModulesLayoutsHeroWithHeadingLayout: HeroWithHeading,
  ModulesLayoutsHeroCarouselLayout: HeroCarousel,
  ModulesLayoutsHeroRandomLayout: HeroRandom,
}

Then in my [page].astro (or wherever I need these layouts):

- - - 
import {
  flexibleContentComponents,
  fragments // these are all of the GraphQL fragments for each layout
} from '@components/FlexibleContent/FlexibleContentComponents.js'

const pageWithLayouts = await getLayoutsByUri(pageSlug, fragments)
let layouts = pageWithLayouts?.data?.modules?.layouts
- - -

layouts.map((layout, index) => {
    const Component = flexibleContentComponents[layout.__typename]
    if (!Component) return null
    return <Component key={index} module={layout} id={pageId} slug={slug} />
})

As you can see, this is very similar to what you have. With this, I send the data from WPGraphQL + ACF with each component. Happy to answer any questions about it.