グローバルインポートと動的インポート
ご存知のとおり、Qwik はデフォルトでアプリのパフォーマンスとスケーラビリティを高めるために、遅延読み込みを自動的に処理します。
この自動最適化の結果として、Vite の動的インポート機能を使用する必要はなく、オプティマイザーと競合するため、使用すべきではありません。
しかし、ディレクトリから多数のファイルを取り込む必要がある場合があり、すべてのファイルパスを入力したくない場合があります。そのような状況では、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
});
方法
Qwik でのimport.meta.glob
の問題は、現在、開発中は機能するがプレビュー/本番環境では機能しないか、プレビュー/本番環境では機能するが、インポートされるファイルの数が増えるにつれて開発サーバーの速度が遅くなることです。
この動作の理由は、eager:false
を使用した import.meta.glob
は、Qwik が処理できない遅延読み込み可能なチャンクを作成するため、本番バンドルを壊します。一方、eager:true
は、Qwik がファイルを通常どおりバンドルできるようにするため、問題を解決するようですが、多くの重いコンポーネントをインポートする場合、特に開発サーバーの速度を低下させます。
今のところの回避策として、"@builder.io/qwik/build"
からビルド時の isDev
ブール値を使用できます。
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 />}</>;
});