Импорт Glob и динамический импорт

Как вы, вероятно, знаете, Qwik заботится о ленивой загрузке для того, чтобы сделать ваше приложение производительным и масштабируемым по умолчанию.

Вследствие этой автоматической оптимизации вам не нужно и не следует использовать функцию Vite dynamic imports, поскольку она конфликтует с optimizer.

Но всё же бывают случаи, когда вам нужно импортировать много файлов из каталога, и вы не хотите вводить все пути к файлам. Для подобных ситуаций можно использовать import.meta.glob.

import.meta.glob

Цель использования import.meta.glob заключается в том, чтобы позволить вам создать компонент-обертку, которому вы можете передать параметр name, чтобы выбрать компонент, который вы хотите импортировать:

<MetaGlobComponent name="file-name" />
<MetaGlobComponent name="another-file-name" />
<MetaGlobComponent name="etc." />

Как написано в документации Vite, import.meta.glob имеет несколько функций, которые позволяют вам указать, как импортировать ваши файлы.

По умолчанию вы можете просто использовать сопоставление шаблонов, чтобы указать, какие файлы должны быть импортированы и из какой папки:

const metaGlobComponents: any = import.meta.glob('/src/components/*');

Но вы также можете передать дополнительные опции, такие как import, as или eager:

const metaGlobComponents: any = import.meta.glob('/src/components/*', {
  import: 'default',
  as: 'raw',
  eager: true, // defaults to false
});

How to

Проблема с import.meta.glob в Qwik заключается в том, что в настоящее время он либо работает в режиме разработки и не работает в preview/production-режимах, либо работает в preview/production, но становится все медленнее и медленнее в режиме разработки по мере увеличения количества импортируемых файлов.

Причина такого поведения в том, что import.meta.glob с eager.false ломает сборку для производственной среды, так как создаёт лениво загружаемые чанки, которые Qwik не знает как обрабатывать. С другой стороны, eager:true вроде бы решает проблему, поскольку позволяет Qwik нормально компоновать файлы, но это также замедляет работу сервера разработки - особенно если вы импортируете с его помощью много тяжелых компонентов.

В качестве обходного пути пока что можно использовать булево значение времени сборки isDev из "@builder.io/qwik/build":

import {
  type Component,
  component$,
  useSignal,
  useTask$,
} from '@builder.io/qwik';
import { isDev } from '@builder.io/qwik/build';
 
const metaGlobComponents: Record<string, any> = import.meta.glob(
  '/src/examples/*',
  {
    import: 'default',
    eager: isDev ? false : true,
  }
);
 
export default component$(() => {
  return (
    <div>
      <MetaGlobExample name="example1" />
      <MetaGlobExample name="example2" />
      <MetaGlobExample name="example3" />
    </div>
  );
});
 
export const MetaGlobExample = component$<{ name: string }>(({ name }) => {
  const MetaGlobComponent = useSignal<Component<any>>();
  const componentPath = `/src/examples/${name}.tsx`;
 
  useTask$(async () => {
    MetaGlobComponent.value = isDev
      ? await metaGlobComponents[componentPath]()
      // We need to call `await metaGlobComponents[componentPath]()` in development as it is `eager:false`
      : metaGlobComponents[componentPath];
      // We need to directly access the `metaGlobComponents[componentPath]` expression in preview/production as it is `eager:true`
  });
 
  return <>{MetaGlobComponent.value && <MetaGlobComponent.value />}</>;
});

Участники

Спасибо всем участникам, которые помогли сделать эту документацию лучше!

  • maiieul