Задать вопрос
  • Происходит ли блокировка при обращении к асинхронным роутам?

    bingo347
    @bingo347 Куратор тега Node.js
    Crazy on performance...
    async function выполняется синхронно до первого await
    Каждый встреченный по ходу выполнения await прерывает функцию, выкидывая из нее вверх по стектрейсу, в случае если это первый await, то продолжит исполняться функция, вызвавшая нашу, но там обычно тоже await, хотя и не обязательно. Так постепенно мы вывалимся в event-loop. Продолжение работы после await вызывается непосредственно из event-loop, так что в этом случае выше по стектрейсу будет только он.
    Когда исполнение в event-loop, он просто берет следующую задачу из очереди. Притом async function - это абстракция над промисами и их колбэками, а они выполняются в очереди микротасок, которую event-loop разбирает пока она не станет пустой.

    Если ближе к примеру в вопросе, то выполнение будет таким:
    1. event-loop вызовет колбэк http сервера, который часть роутера
    2. роутер вызовет наш колбэк, он это может делать как синхронно так и асинхронно (express делает синхронно)
    3. Наш колбэк отправит запрос в БД, получит его промис и остановится на await
    4. мы вернем управление роутеру, а он модулю http и в итоге все вернется в event-loop
    5. event-loop возьмет следующую таску из очереди, это может быть как запрос к http серверу, так и ответ от БД
    Ответ написан
    2 комментария
  • Как правильно хранить данные и создавать новые блоки без перерисовки всего компонента при скролле?

    liaFcipE
    @liaFcipE
    В общем виде, я бы делал как-то так:

    const LIMIT = 10;
    
    const getProducts = async (offset, limit) => { ... }
    
    function App () {
      const [offset, setOffset] = useState(0);
      const [products, setProducts] = useState([])
    
      useEffect(() => {
        getProducts(offset, LIMIT).then(products => setProducts(v => [...v, ...products]))
      }, [offset]);
    
      return <RenderProducts onScroll={() => { // increment offset }} />
    }


    Конечно, ваш бекенд должен уметь отдавать данные по limit & offset.
    И лучше вынести всю работу с данными в стор, тогда не нужен будет уродливый useEffect.

    Что-то вроде (nanostores):

    // store.ts
    const LIMIT = 30;
    
    export const $products = map({
      offset: 0,
      products: [],
      isLoading: true
    })
    
    onMount($products, () => {
      fetchProducts()
    })
    
    const fetchProducts = action($products, "fetchProducts", async store => {
      const { products, offset } = store.get();
    
      // TODO: add error handling
      store.setKey("isLoading", true);
      const newPartOfProducts = await api.getProducts(offset, LIMIT);
      store.setKey("products", [...products, ...newPartOfProducts ]);
      store.setKey("isLoading", false);
    });
    
    const incrementOffset = action($products, "incrementOffset", store => {
      const { offset } = store.get();
      store.setKey("offset", offset + LIMIT);
      fetchProducts()
    })
    
    export const $productsMutations = { incrementOffset }
    
    // App.tsx
    
    function App () {
      const { isLoading, products } = useStore($products)
    
      return (
        <Fragment>
          <RenderProducts onScroll={$productsMutations.incrementOffset} products={products} />
          {isLoading && <LoadingIndicator />}
        </Fragment>
      )
    }
    Ответ написан
    6 комментариев
  • Какого вида данных запрос делают на сервер при работе с пагинацией?

    yarkov
    @yarkov
    Помог ответ? Отметь решением.
    А как на клиенте узнают максимальное количество продуктов?


    GET /posts?page=2&perPage=10
    
    Response 200 OK
    {
      data: [posts collection],
      meta: {
        totalItems: 123 // количество всех постов
      }
    }
    Ответ написан
    3 комментария
  • В каких случаях используют useEffect без второго аргумента в виде массива?

    Alexandroppolus
    @Alexandroppolus
    кодир
    использовал для кейса, когда есть реф и у этого рефа current мог меняться во время жизни компонента.

    вкратце:
    const ref = useRef<HTMLDivElement>(null);
    const prevRef = useRef<HTMLDivElement>(null);
    
    useEffect(() => {
        if (ref.current === prevRef.current) { return; }
        prevRef.current = ref.current;
    
        // реф поменялся, что-то делаем
    });


    по факту я здесь делаю то же самое, что происходит в депенденсах, но депенденсы непригодны:
    1) [ref] - бесполезно, будет один и тот же, эффект не перевызовется
    2) [ref.current] - бесполезно, реф меняется после фазы рендера.
    Ответ написан
  • В каком месте начинается создание элементов в цепочке от createRoot?

    i229194964
    @i229194964
    Веб разработчик
    const root = ReactDOM.createRoot(document.getElementById('root'));
    const container = ReactDOM.createContainer(document.getElementById('root'), false, false);
    ReactDOM.updateContainer(element, container, null, () => {
      // Callback, который вызывается после завершения обновления
    });
    const fiberRoot = ReactDOM.createFiberRoot(container, false);
    Ответ написан
    Комментировать
  • Как настроить статику при редиректе?

    emekhanikov
    @emekhanikov
    Разработчик и архитектор программного обеспечения
    Добрый день,

    Можно так:

    server {
        listen 80 default_server;
        listen [::]:80 default_server;
    
        location / {
            return 301 https://$host$request_uri;
        }
    }
    
    server {
        listen 443 ssl http2;
        listen [::]:443 ssl http2;
        
      ssl_certificate /etc/letsencrypt/live/site.com/fullchain.pem;
      ssl_certificate_key /etc/letsencrypt/live/site.com/privkey.pem;
    
        ssl_session_timeout 1d;
        ssl_session_cache shared:MozSSL:10m;  # about 40000 sessions
        ssl_session_tickets off;
    
        # curl https://ssl-config.mozilla.org/ffdhe2048.txt > /path/to/dhparam
    #    ssl_dhparam /path/to/dhparam;
    
        # intermediate configuration
        ssl_protocols TLSv1.2 TLSv1.3;
        ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-CHACHA20-POLY1305;
        ssl_prefer_server_ciphers off;
    
        # HSTS (ngx_http_headers_module is required) (63072000 seconds)
        add_header Strict-Transport-Security "max-age=63072000" always;
    
        ssl_stapling on;
        ssl_stapling_verify on;
    
        location / {
          root /var/www/html/;
          autoindex off;
          if ( $request_uri ~ "/index.html" ) {
            rewrite ^(|/(.*))/index\.html$ /$2 permanent;
          }
        }
    
    }


    С уважением,
    Евгений
    Ответ написан
    4 комментария
  • Для чего нужно дублирование в папках avaliable и enabled?

    paran0id
    @paran0id
    Умный, но ленивый
    Не дублирование, а symlink. Примерно как ярлык. В avaliable храним конфигурацию хоста, в enabled кидаем симлинк, чтобы включить его. Nginx считывает конфиги из enabled. Если хотим выключить, удаляем симлинк, а файл конфигурации остается лежать.
    Ответ написан
    2 комментария
  • Как в исходные файлы реакта попадает переменная __DEV__?

    Mike_Ro
    @Mike_Ro
    Python, JS, WordPress, SEO, Bots, Adversting
    Переменная __DEV__ в исходных кодах React используется для определения режима сборки: разработка или продакшн. Это позволяет добавлять или исключать определенный код в зависимости от режима, что может быть полезно для добавления дополнительных предупреждений, проверок и другого кода, который полезен только во время разработки.

    На практике __DEV__ не определяется непосредственно в исходных файлах React. Вместо этого, она обычно заменяется на этапе сборки с помощью инструментов, таких как Webpack или Babel.

    Вот как это обычно работает:

    1. В исходном коде React, вы можете увидеть конструкции вроде:
    if (__DEV__) {
      console.warn('Some warning message');
    }

    2. Когда React собирается для режима разработки, __DEV__ заменяется на true, а для режима продакшн - на false.

    3. Инструменты сборки, такие как UglifyJS или Terser, затем оптимизируют этот код, удаляя условные блоки, которые никогда не выполняются. Например, если __DEV__ заменяется на false, то весь блок if (__DEV__) { ... } будет удален при минификации.

    Для того чтобы замена __DEV__ работала, вы обычно настраиваете ваш инструмент сборки (например, Webpack) с помощью плагинов, таких как DefinePlugin для Webpack, который заменяет определенные токены в исходном коде на заданные значения.

    В случае с React и многими другими библиотеками, процесс сборки заботится о замене таких переменных, чтобы упростить разработку и оптимизировать выпускаемый код для продакшена.

    На правах копипаста, самому в лом писать...
    Ответ написан
    1 комментарий
  • Как в Ubuntu настроить автозапуск приложений через pm2?

    VoidVolker
    @VoidVolker
    Dark side eye. А у нас печеньки! А у вас?
    А что, открыть документацию и следовать инструкции не получается? https://pm2.keymetrics.io/docs/usage/startup/
    Ответ написан
    1 комментарий
  • В каких случаях используют as keyof typeof?

    @daniel_wesson
    Как правило странно в массиве объектов использовать строковые ключи, а не обычные индексы. Лучше сделать
    type Posts = Post[]
    keyof typeof вернет список всех возможных ключей объекта (в вашем случе просто string). Поэтому если вы их не определяете где-то, то в данном случае as keyof typeof точно не нужен.

    Например в объекте { id: 1, title: 'Test', description: 'Описание' }, keyof typeof вернет тип "id" | "title" | "description"
    Ответ написан
    Комментировать
  • Как типизировать вложенного объекта в объекте в одну строку?

    @HungryGrizzzly
    Сумасшедший кросс
    Тут вопрос к типизации props.name. TS считает его просто стрингом, следовательно, поля может не быть в blogPosts, а должен считать keyof typeof blogPosts. Тогда все будет хорошо, но надо видеть весь код, чтоб подсказать, как поправить. Самый же "ламерский" способ:
    const result = blogPosts[props.name as keyof typeof blogPosts]
    Ответ написан
    2 комментария
  • Как типизировать вложенного объекта в объекте в одну строку?

    Aetae
    @Aetae Куратор тега TypeScript
    Тлен
    Тупо скастовать можно так:
    const result = (blogPosts as Posts)[props.name]

    Но это не правильно, по хорошему ты должен изначально убедиться, что blogPosts - нужного типа:
    // тайпргард: тут проверка что posts действительно Posts; 
    const isPosts = (posts: unknown): posts is Posts => !!posts 
      && typeof posts === 'object' 
    //&& ... ;
    
    if (!isPosts(blogPosts)) throw new Error('wrong blogPosts');
    
    const result = blogPosts[props.name];
    Ответ написан
    4 комментария
  • Как в Next создается шаблон страницы под генерацию данных с маршрутом?

    szQocks
    @szQocks
    если юзаешь next 13 + с app директорией, забудь про всякие getStaticProps и getServerSideProps

    в 13 нексте, там все компоненты по умолчанию - серверные, а в серверных компонентах доступен расширенный fetch через которые и получаешь данные где хочешь + это и есть грубо говоря твои новые getStaticProps и getServerSideProps, и самый прикол в том что и в клиентских и в серверных компонентах на выходе получаешь уже отрисованный html

    на уровне app/blog - можешь создать layout.tsx, а все вложенные папки это и будут children которые попадают в этот layout.tsx - типа вложенных страниц, но на самом деле не так, layout.tsx - это просто обёртка

    const BlogLayout = ({ children }) => {
        return (
            <section>
                <SomeComponent/>
                {children}
            </section>
        )
    };
    
    export default BlogLayout ;
    Ответ написан
    Комментировать
  • В каких случаях надо испоinterfacce, а не type?

    Везде используй interface, если это возможно.
    type сильно влияет на скорость компиляции и проверки типов.
    Ответ написан
    4 комментария
  • В каких случаях надо испоinterfacce, а не type?

    bingo347
    @bingo347 Куратор тега TypeScript
    Crazy on performance...
    interface поддерживает extends (который компилируется быстрее чем intersection (&) как верно подметил Василий Банников )
    interface A extends B, C {}
    interface B {}
    type C = {}; // interface вполне может extends из type


    interface поддерживает declaration merging
    interface A {
      a: number;
    }
    interface A {
      b: number;
    }
    const a: A = {a: 1, b: 2};


    type поддерживает вычисления типа на верхнем уровнеtype A = B | C; // на interface такого не выразишь

    В остальном различий нет.
    Declaration merging может подложить жабу в реальном проекте, но полезен при написании библиотек, которые могут быть расширены извне (плагины jQuery например)
    В целом type более универсален и надежен. И не сильно он медленнее. Вся его медленность заключается в том, что компилятор производит вычисления типа, которые так же возможны и в полях интерфейса, а значит присутствуют и там.
    Для Java/C# разрабов, читающих TS, interface более понятная конструкция (хотя и обманчиво).

    В целом все зависит от стайл гайда, который примет команда. Главное чтоб везде одинаково было.
    Ответ написан
    2 комментария
  • За счет чего Bun и Deno работают быстрее Node?

    bingo347
    @bingo347 Куратор тега Node.js
    Crazy on performance...
    У bun потенциально может быть быстрее старт приложения за счет использования движка JavaScriptCore вместо V8 в node/deno. Вот только у V8 на сегодня поддержка всех нюансов ECMAScript самая близкая к 100%. А старт рантайма происходит лишь 1 раз во время жизни приложения. Считать ли это профитом - вопрос философский.
    Ну и ИМХО, если биться за скорость путем смены движка, то я бы лучше взял QuickJS.

    Еще потенциальный выигрыш может быть за счет переписывания тех частей, что в node реализованы на JS. В node на самом деле очень многое на JS сделано. 100% встроенных модулей написано на JS, где уже под капотом дергаются функции из C++. Я не смотрел исходники deno/bun, но экспериментировал с v8 на Rust (спасибо deno за нормальный биндинг). Работать это будет быстрее, вот только обрабатывать JS Promise из нативки то еще приключение, и хочется делать это пореже за счет JS прослоек, как собственно и происходит в node.
    Rust (deno) и Zig (bun) по скорости сравнимы с плюсами (где-то быстрее, а где-то медленнее, но в среднем примерно одинаково). Самый большой оверхед в языках с рантаймом создает рантайм (сборка мусора, JIT компилятор и т.д.), у C++, Rust и Zig подкапотного рантайма почти нет, у JS - целый V8/другие движки.

    Ну и еще момент, что bun, что deno работают с ts из коробки. Вот только TypeScript - это язык у которого нет спеки, есть открытый код компилятора (в котором черт ногу сломит), есть release notes, а спеки нет. А значит гарантировать 100% совместимость с tsc не может никто. Хотя это проблема не только этих сред, но еще и WebStorm и babel-typescript например. Хотя на сколько понял они пошли путем babel - просто затранспайлить (по сути выкинуть все типы), вот только babel в некоторых кейсах все же ломает код...
    Ответ написан
    1 комментарий
  • Почему не подключается к локальному домену от nginx?

    Viji
    @Viji
    DevOps Engineer
    Boris007

    что значит к локальному домену test-site.ru? публичный IP адрес для домена test-site.ru должен прописан быть либо в dns регистратора домена, либо в файле hosts Windows https://www.nublue.co.uk/guides/edit-hosts-file/#:... - для локальной разработки. Иначе откуда система знает, куда идти за сайтом?
    Ответ написан
    1 комментарий
  • Как в реакте понять, почему компонент всегда отрисовывается 2 раза?

    В реакте стоит режим StrictMode, он и отрисовывает второй раз, это из функционального программирования для проверки что функции чистые.
    Но не волнуйся это работает только в режиме DEV
    Ответ написан
    2 комментария