Лучшие практики

Встроенные операции в шаблонах

Оптимизатор Qwik может лучше оптимизировать реактивность приложения, если операции встроены в шаблон.

Неоптимальная реализация
// Не делай так!
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} - Текущее значение: { 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'} - Текущее значение: {signal.value}
      </div>
    </div>
  );
});

Используйте useVisibleTask$() только в крайнем случае

Несмотря на удобство, useVisibleTask$() немедленно запускает код и блокирует основной поток, предотвращая взаимодействие с пользователем до завершения задачи. Вы можете думать о ней, как о спасательном люке.

В случае сомнений вместо «useVisibleTask$()» используйте:

  • useTask$() -> выполнение кода в режиме SSR;
  • useOn() -> слушает события на корневом элементе текущего компонента;
  • useOnWindow() -> слушает события на объекте window;
  • useOnDocument() -> слушает события на объекте document.

Однако иногда это единственный способ добиться результата.

В этом случае вы можете добавить // eslint-disable-next-line qwik/no-use-visible-task в строку перед "useVisibleTask$", чтобы убрать предупреждение.

Регистрируйте события DOM с помощью useOn(), useOnWindow() или useOnDocument()

Qwik позволяет регистрировать слушателей событий декларативным способом, используя useOn() или с помощью JSX.

При использовании useVisibleTask$() для программной регистрации событий, мы загружаем и выполняем JavaScript сразу, даже если событие не сработает.

Неоптимальная реализация
// Не делай так!
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);
    // Вручную очищать слушатель события не надо!
  })
);

Избегайте доступа к location из объекта window.

Не обращайтесь напрямую к window.location, вместо этого используйте хук useLocation().

Неоптимальная реализация
// Не делай так!
useVisibleTask$(()=> {
    if (window.location.href).includes('foo') {
        //...делаем что-либо
    }
})
// или
if (typeof window !== "undefined") {
    const queryParams = new URLSearchParams(window.location.search);
    const query: Record<string, string> = {};
    queryParams.forEach((value, key) => {
        query[key] = value;
    })
    doTheThing(query);
}

Многие действия, связанные с информацией о местоположении, могут быть выполнены во время первоначального рендера на стороне сервера, в результате чего получается чистый HTML без каких-либо накладных расходов на JavaScript.

Заставляя эту логику работать на стороне клиента, мы увеличиваем количество JavaScript-кода, требующего немедленной загрузки.

Использование шаблона if typeof window !== "undefined" может привести к тому, что код будет пропущен. На сервере этот блок кода будет пропущен, поскольку там объект window не определён.

Хотя разработчики могут привыкнуть к тому, что код выполняется дважды, Qwik устраняет эту необходимость, предлагая более эффективный подход.

Оптимальная реализация
// Делай так!
const location = useLocation();
 
if (location.url.href.includes('foo')) {
  //...делаем что-либо
}
 
doTheThing(location.url.searchParams);

Исключение

При использовании SSG для статических файлов неизбежно полагаться на сервер без текущей информации о местоположении во время сборки.

Однако будьте осторожны! Если требуемая информация (например, параметры запроса) не нужна до тех пор, пока не произойдет событие пользователя, включите проверку в код обработки событий.

Такой подход помогает предотвратить немедленную загрузку JavaScript-кода и повышает производительность.

Смотри: Документация useLocation()

Участники

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

  • mhevery
  • the-r3aper7
  • manucorporat
  • jakovljevic-mladen
  • kerbelp
  • wfairclough
  • cunzaizhuyi
  • reemardelarosa
  • un33k
  • egmaleta
  • mugan86
  • octoper
  • mrhoodz
  • VinuB-Dev
  • anartzdev
  • adamdbradley
  • hamatoyogi
  • maiieul