Задать вопрос
  • Как работает skipHydrate в pinia?

    @null_object
    Процесс гидратации - это процесс восстановления состояния. Обычно сервер при SSR генерирует HTML и встраивает "гидратирующее состояние" в виде window.__INITIAL_STATE__ или аналогичного объекта прямо в HTML. Клиент потом использует эти данные, чтобы инициализировать своё состояние.

    То есть весь происходит примерно следующая последовательность действий:
    1. Выполняется код вашего стора на сервере
    2. Вычисленное состояние (все сторы) сериализуется и например встраивается в html
    3. На клиенте код стора выполняется повторно, и если есть сериализованное состояние из прошлого шага, оно перезаписывает текущее


    Отвечая на ваш вопрос:
    1) Состояние оно получит в любом случае и на сервере, и на клиенте, но будет помечено, как не требующее восстановления
    2) Будет то состояние, которые вы зададите
    Ответ написан
    5 комментариев
  • Как подружить 1 стор Pinia с разными инстансами одного и того же виджета?

    @null_object
    Pinia не очень удобна, если вы хотите делать на основе нее фабрики, единственный правильный способ работы со стором - создавать внутри состояния, функции и возвращать их. Также надо помнить, что все созданные сторы Pinia живут вплоть до закрытия вкладки и занимают память.

    Как вариант, можно попробовать подобную реализацию
    interface InputState {
      value: Ref<string>;
      props: object;
    }
    
    const useStore = defineStore(`inputs`,  () => {
      const inputs = new Map<string, InputState>();
    
      function defineInput(id: string, value: Ref<string>, props = {}) {
        inputs.set(id, { value, props });
      }
    
      return { inputs, defineInput };
    })


    В качестве альтернативы Pinia можно посмотреть на композаблы из vueuse: createGlobalState и createInjectionState. Первый практически полный аналог Pinia, но более легковесный, второй позволяет создавать глобальное состояние только на поддерево компонентов и не будет занимать память, если это состояние не нужно.

    P.S. задачу вы не озвучили, но почти наверняка, как вам уже написали, Pinia вам не нужна
    Ответ написан
    2 комментария
  • Почему не передаются компоненты в слот?

    @null_object
    Вероятно, Nuxt не может найти файл лэйаута, потому что директория с ними не в корне проекта, поменять можно в конфиге. Это касается всех стандартных директорий.
    export default defineNuxtConfig({
      dir: {
        layouts: 'app/layouts',
      },
    })
    Ответ написан
    Комментировать
  • Как динамически подключать google reCaptcha v3 на nuxt 3?

    @null_object
    Как вариант, переделать код библиотеки под нужный композабл, тогда не нужно будет на глобальный объект Vue цеплять инстанс рекапчи
    Ответ написан
    Комментировать
  • Почему разное значение переменной в NUXT 3?

    @null_object
    Это так не работает. Передача состояние с сервера на клиент не происходит сама по себе, его нужно прокидывать, для этого в Nuxt сделано много утилит (useAsyncData, useLazyAsyncData, useNuxtData, useState и т.д.), которые пляшут вокруг большого сериализуемого стейта, который на клиенте обратно десериализуется. И useFetch использует это под капотом.

    То есть ваш код работает так:
    1. На сервере вызывается функция getPosts
    2. Выполняется запрос, результат сохраняется в стейт накста, в total.value записывается значение
    3. На клиенте вызывается функция getPosts
    4. Но тут уже запрос не выполняется, только вычитывается значение из стейта, соответственно onResponse не вызывается

    Решить это можно несколькими путями: создать отдельный стейт для total, либо к ответу в onResponse дописывать значение заголовка.

    <script setup lang="ts">
    const { data } = useFetch('https://jsonplaceholder.typicode.com/todos/1', {
      onResponse({ response, options }) {
        // дописываем в data значение заголовка
        response._data.type = response.headers.get('Content-Type');;
      },
    });
    </script>


    Сериализованное состояние, которое идет с сервера на клиент можно дебажить через Nuxt Devtools
    67ae28550973e616213331.png
    Ответ написан
  • Как задеплоить vite react сайт на хостинг timeweb?

    @null_object
    Если вы делали обычное SPA приложение, после билда которого у вас есть набор html, css, js файлов, то просто загрузить их на vps недостаточно, нужен веб-сервер, который эти файлы будет раздавать. Часто для этого ставять Nginx, в конфиге которого указывается директория с собранными файлами, например так
    server {
        listen 80;
        server_name your-domain.com;
    
        root /path/to/your/dist;
        index index.html;
    
        location / {
            try_files $uri /index.html;
        }
    }


    Если нет желания разбираться с конфигами, то проще всего воспользоваться сервисами, которые умеют автоматически деплоить проекты из репозитория, те же Apps у Timeweb
    Ответ написан
    Комментировать
  • Чем так страшен верхне-уровненый await в script setup?

    @null_object
    Если у вас версия vue >3.2, то страшного ничего нет. Проблема в том, что у vue рендер синхронный и после первого await в setup теряется контекст монтируемого компонента, который используется много где под капотом - реактивные функция вроде watch, хуки жизненного цикла и т.д. Это можно обойти, а начиная с vue 3.2 это сделано на уровне компилятора sfc. Подробно с примерами про это написано тут.

    Если говорить про useAsyncData - это уже композабл самого nuxt, нужный в первую очередь для дедупликации данных при ssr. По умолчанию данные запрашиваются на сервере, серилизуются и передаются вместе с html (пример на скриншоте). Этот композабл можно использовать и без await, при условии, что запрос вам нужно выполнять только на клиенте (server: false), тогда обработку ошибок надо будет делать через watch(error, ...)
    67659c49b753a027017230.png
    Ответ написан
    1 комментарий
  • Как правильно типизировать vue generic components?

    @null_object
    const virtualizationContainer = ref<typeof VVirtualizationContainer | null>(null);


    playground

    6742b6fc6e199037664340.png
    Ответ написан
    3 комментария
  • Как можно вытащить типы пропсов из определения компонента?

    @null_object Автор вопроса
    type ComponentProps<ComponentDefinition> = ComponentDefinition extends { new (): { $props: infer P } } ? P : never;
    Ответ написан
    Комментировать
  • Как сгруппировать значения массива?

    @null_object
    const array = ['part1-item1', 'part1-item2', 'part2-item1', 'part3-item1'];
    
    const result = array.reduce((acc, rec) => {
      const [part, item] = rec.split('-');
      if (!acc[part]) {
        acc[part] = [item];
      } else {
        acc[part].push(item);
      }
      return acc;
    }, {});
    Ответ написан
    2 комментария
  • Возможно ли впихнуть фронтенд на nuxt.js и бекенд на express.js на один сервер?

    @null_object
    Для чего-то небольшого можно обойтись встроенными возможностями Nuxt, он позволяет делать бэкенд рядом с фронтедом с помощью своего сервера - Nitro. Подробнее об этом есть в документации Nuxt и документации Nitro.

    Если нужно, Nitro может использовать и другие решения (Express, Hono и др.) про это есть видео + дока.
    Ответ написан
    Комментировать
  • Как заставить hmr в vite подключатсья по wss?

    @null_object
    Как уже написал Aetae, конфигурацией протокола занимается nuxt, но монкипатчить не обязательно, переопределить конфиг можно через хук, например так
    export default defineNuxtConfig({
      hooks: {
        'vite:extendConfig': function (vite) {
          vite.server.hmr = {
            protocol: 'wss',
          };
        },
      },
    });
    Ответ написан
    Комментировать
  • Как правильно отобразить компоненты в Components Tree Nuxt 3?

    @null_object
    Это стандартное поведение компонента <NuxtPage /> и не является проблемой, он внутри себя использует <RouterView /> из vue-router в который добавляется внутренняя логика Nuxt (например добавление Transitions если они указаны в настройках). Anonymous Component на самом деле - компонент RouteProvider, который занимается перерисовкой страниц. В общем, просто обертка фреймворка для роутинга.

    RouteProvider добавляется тут. Код самого провайдера можно тут посмотреть.
    Ответ написан
    Комментировать
  • Есть ли рекомендуемый порядок следования атрибутов во vue?

    @null_object
    Еще есть vue-eslint правило по порядку атрибутов
    Ответ написан
    Комментировать
  • Как лучше переписать условие?

    @null_object
    export const Footer = (props?: IFooterProps) => {
        return (
            <View style={styles.container}>
                {props && props.button ? (
                  <>
                     <RNHoleView style={styles.background} holes={[hole]}>
                          <View style={styles.maskBorder}></View>
                      </RNHoleView>
                      {props.button}
                   </>
                ) : (
                  <View style={styles.background}></View>
                )}
            </View>
        );
    };
    Ответ написан
    3 комментария
  • Как добавить количество wc -l в конец строки в виде значения?

    @null_object
    echo -n "текущее количество нескрытых файлов и директорий в /usr/bin равно:" > results.txt | ls /usr/bin  | wc -l >>  results.txt
    Ответ написан
    3 комментария
  • Vue 3 Composition API как обратиться к функции через this.$refs?

    @null_object
    Чтобы напрямую вызывать методы инстанса компонента, нужно методы сделать публичными. Для этого есть expose в Options API и defineExpose для Composition API

    Child.vue
    <script setup>
    const foo = ref('foo')
    const bar = () => console.log('bar')
    
    defineExpose({
      foo,
      bar,
    })
    </script>

    Parent.vue
    <template>
      <Child ref="child" />
    </template>
    
    <script setup>
    const child = ref(null);
    
    onMounted(() => {
      console.log(child.value.foo)
      console.log(child.value.bar())
    })
    </script>


    Т. е. без доработок код из этого репозитория не заработает
    Ответ написан
    Комментировать
  • Как работает runtime config в Nuxt 3?

    @null_object
    Под рантайм конфигурацией понимаются переменные окружения, которые может подхватить приложение после сборки. Если собрать обычное SPA, значения этих переменных зашиваются на этапе сборки прямо в код и их поменять можно только повторной пересборкой.

    То, что вы в консоли установили переменную окружения и она сразу попала в приложения - скорее всего совпадение. Девопсы правильно сказали про их статичность, так что по какой-то причине у вас сработал hmr и подхватились новые переменные.

    Найти конкретную причину всех возможных триггеров для перезагрузки в коде будет достаточно затруднительно, т.к. эта логика сильно размазана по пакетам Nuxt -> Nitro -> Vite -> Chokidar
    Ответ написан
    Комментировать
  • Как использовать хуки NUXT в модулях?

    @null_object
    Если нужны именно хуки
    const nuxtApp = useNuxtApp();
    
    const loadingStartHook = nuxtApp.hook('page:loading:start', () => {
      ...
    });
    
    const loadingFinishHook = nuxtApp.hook('page:loading:end', () => {
      ...
    });
    
    const unsubError = nuxtApp.hook('vue:error', () => ...)


    В какой-то из версий добавили встроенный композабл useLoadingIndicator . Это удобная обертка над этими хуками, можно в исходниках глянуть.

    Использовать достаточно просто
    const { progress, isLoading } = useLoadingIndicator();


    Тут можно посмотреть пример кастомного индикатора
    Ответ написан
    Комментировать
  • Nuxt Supabase Как решить ошибку 500 "client.from is not a function"?

    @null_object
    serverSupabaseClient возвращает Promise, нужно добавить await

    import { serverSupabaseClient } from '#supabase/server'
    
    export default eventHandler(async (event) => {
        const client = await serverSupabaseClient(event)
        const { data } = await client.from('users').select("*")
        return { users: data }
    })
    Ответ написан