ベストプラクティス
テンプレート内のインライン操作
操作がテンプレートにインライン化されている場合、Qwikオプティマイザーはアプリケーションのリアクティビティをより最適化できます。
// Don't do this!
export default component$(() => {
const signal = useSignal(0);
const isBiggerThanZero = signal.value > 0 ? 'Bigger than zero' : 'Smaller than zero';
return (
<div>
<button onClick$={() => signal.value++}>+</button>
<button onClick$={() => signal.value--}>-</button>
<div>{isBiggerThanZero} - Current value: { signal.value }</div>
</div>
);
});
上記の実装では、シグナルが変更されるとテンプレート全体が再レンダリングされます。これは、 `isBiggerThanZero` がテンプレートにインライン化されていないためです。
export default component$(() => {
const signal = useSignal(0);
return (
<div>
<button onClick$={() => signal.value++}>+</button>
<button onClick$={() => signal.value--}>-</button>
<div>
{signal.value > 0 ? 'Bigger than zero' : 'Smaller than zero'} - Current
value: {signal.value}
</div>
</div>
);
});
シグナルの読み取りを `useTask$` または `useComputed$` に移動する
これは上記のヒントに似ています。
Qwikがシグナル/ストア値を「読み取る」たびに、「読み取り」が行われている関数は、そのシグナルの変更ごとに再実行されます。
そのため、可能な限り、コンポーネント関数内ではなく、 `useTask$` または `useComputed$` 関数内で値を「読み取る」(そして追跡する)方が良いでしょう。
そうでない場合、コンポーネント関数は変更ごとに再実行されます。
// Don't do this!
export default component$(() => {
const count = useSignal(1);
const doubleCount = count.value*2;
return (
<div>{doubleCount}</div>
);
});
上記の実装では、シグナルが変更されるとテンプレート全体が再レンダリングされます。
以下では、 `count.value` が変更された場合、 `useComputed$` 関数のみが再実行されます。
export default component$(() => {
const count = useSignal(1);
const dobuleCount = useComputed$(() => count.value*2);
return (
<div>{doubleCount.value}</div>
);
});
`useVisibleTask$()` は最後の手段として使用する
便利な反面、`useVisibleTask$()` はコードを積極的に実行し、メインスレッドをブロックするため、タスクが完了するまでユーザーインタラクションができません。これは、緊急脱出手段と考えることができます。
不明な場合は、 "useVisibleTask$()" の代わりに以下を使用してください。
- `useTask$()` -> SSRモードでコードを実行します。
- `useOn()` -> `現在のコンポーネント` のルート要素でイベントをリッスンします。
- `useOnWindow()` -> `window` オブジェクトでイベントをリッスンします。
- `useOnDocument()` -> `document` オブジェクトでイベントをリッスンします。
ただし、結果を達成する唯一の方法である場合があります。
その場合は、 "useVisibleTask$" の前の行に `// eslint-disable-next-line qwik/no-use-visible-task` を追加して警告を削除できます。
`useOn()`、 `useOnWindow()`、または `useOnDocument()` でDOMイベントを登録する
Qwikでは、 `useOn()` またはJSXを使用して、宣言的な方法でイベントリスナーを登録できます。
`useVisibleTask$()` を使用してプログラムでイベントを登録する場合、イベントがトリガーされない場合でも、JavaScriptを積極的にダウンロードして実行しています。
// Don't do this!
useVisibleTask$(({ cleanup }) => {
const listener = (event) => {
const mouseEvent = event as MouseEvent;
console.log(mouseEvent.x, mouseEvent.y);
};
document.addEventListener('mousemove', listener);
cleanup(() => {
document.removeEventListener('mousemove', listener);
});
});
上記の実装では、ユーザーイベントに正確に反応するのではなく、より多くのJavaScriptが積極的にロードされます。初期JavaScriptの読み込み量の増加は、アプリのパフォーマンス低下につながります。
代わりに、 `useOnDocument()` フックを使用して `document` オブジェクトにイベントを登録することで、QwikはイベントがトリガーされるまでJSを実行しません。
useOnDocument(
'mousemove',
$((event) => {
const mouseEvent = event as MouseEvent;
console.log(mouseEvent.x, mouseEvent.y);
// No manual clean up required!
})
);
`window` オブジェクトからロケーションにアクセスしない
`window.location` に直接アクセスしないでください。代わりに `useLocation()` フックを使用してください。
// Don't do this!
useVisibleTask$(()=> {
if (window.location.href).includes('foo') {
//... do the thing
}
})
// or
useTask$(() => {
if (isBrowser) {
if (window.location.href).includes('foo') {
//... do the thing
}
}
})
ロケーション情報に関連する多くのアクションは、初期サーバーサイドレンダリング中に実行できるため、JavaScriptのオーバーヘッドなしで純粋なHTMLが生成されます。
このロジックをクライアントサイドで強制的に実行すると、初期JavaScriptが増加し、積極的な読み込みが発生します。
// Do this!
const location = useLocation();
if (location.url.href.includes('foo')) {
// Do the thing
}
例外
純粋に静的なファイルにSSGを使用する場合、ビルド時に現在のロケーション情報がないサーバーに依存することは避けられません。
ただし、注意が必要です。必要な情報(クエリパラメータなど)がユーザーイベントが発生するまで必要ない場合は、イベントハンドリングコード内にチェックを組み込んでください。
このアプローチは、JavaScriptの積極的な読み込みを防ぎ、パフォーマンスを向上させるのに役立ちます。