• Разработка более быстрых приложений на Vue.js
    0
    Прекрасный пример, того как НЕ НАДО делать приложения на Vue.js.
  • React Token Auth
    0
    Что такое JWT вы можете загуглить.
    Объясню что меня удивляет в ваших ответах:
    1. Вы пишете:
    Минус лишь в том что при каждом получении access токена идет запрос в базу.

    Т. е. логично предположить что при обычном запросе вы к базе не обращаетесь. И это правильно. От части это преимущество использования JWT. Но в то же время вы пишете:
    Убил в базе refresh, новый access не получишь и все access выписанные c этим refresh тоже не работают.

    Получается что вы всеравно каждый раз лезете в базу чтобы достать оттуда refresh токен для проверки access токена.

    2. При использовании JWT refresh токен используется для выдачи нового токена, а для валидации access токена он не требуется, так как там сверяется сигнатура. Исходя из ваших слов — у вас не так.

    3. При использовании JWT refresh токен является ОДНОРАЗОВЫМ. И его нужно беречь еще больше чем access токен, так как даже если у вас украдут только access токен, то пользоваться им смогут только пока он не устареет (обычно минут 15, а в вашем случае всего 2 месяца). А если украдут оба токена, то пользоваться ими смогут бесконечно.

    4. Вы пишете:
    Отправил пользователь 5ть запросов параллельно получил 5ть access токенов, если они в запросе не валидны.

    Итак пришел первый запрос. Сервер формирует новый access (у вас refresh) токен — старый стирает. Получается что остальные запросы со старыми токенами должны быть невалидными так как в них зашит старый refresh токен. Каким образом получается что у вас они всеравно получат новые токены?
  • React Token Auth
    0
    ОМГ. Я понял. Ваш JWT это не JWT.
  • React Token Auth
    0
    Я храню в localStorage или в куках — по разному.
    Я не говорю что вы сделали что-то ужасное. Просто почему бы вам вообще не отказаться от refresh токена? Пусть будет только access и все.
    Вот тогда у вас действительно не будет заморочек. А сейчас получается у вас возможен такой вариант:
    1. Клиент отправит на сервер несколько запросов одновременно с устаревшим токеном
    2. В запросе, который дойдет до сервера первым — будет заменен токен
    3. Все остальные запросы будут отклонены, так как в них токен еще старый (истекший и с уже невалидным refresh токеном)
  • React Token Auth
    0

    Во первых не в блокнот. И упепеть его могут, но не так легко как access token.
    Во вторых можно и без рефреш токена, но его тогда можно просто не обновлять. Зачем зашивать его в access?
    Ну а отпечаток это хорошо и правильно, но к моему вопросу не относится.

  • React Token Auth
    0
    Чтоооо??? 0_о Зачем он тогда вообще вам нужен? Refresh token нужен для повышения безопасности если украден access token. А у вас получается что если украли access token, то украли и refresh token.
  • React Token Auth
    0
    1. Понял. Спасибо.
    2. Насколько я понимаю это избавляет от проблем с разными часовыми поясами, но если на устройстве часы просто отстают, тогда же NumericDate на устройстве будет меньше чем на сервере?! Хотя синхронизацию времени наверное тоже надо оставить на совести пользователя.
    3. Спасибо. Я тоже пришел к такому варианту. Или же каждый раз брать токен из localStorage. Интересно было как вы это решили.
    4. Четвертый вопрос я дописал позже, и вы на него не ответили. )
  • React Token Auth
    0
    Извиняюсь, но мой английский еще не настолько хорош, чтобы грамотно сформулировать этот вопрос, поэтому я спрошу на русском.

    Спасибо за статью. Я тоже долгое время занимался данной задачей.
    Скажите что вы делаете в следующих случаях:
    1. Что происходит когда токен становится невалидным и его обновление проходит неудачно?
    2. Что если время на устройстве пользователя не совпадает с временем на сервере? Ведь тогда isExpired() может работать не корректно.
    3. Как быть если сайт открыт в двух вкладках одновременно и на одной из них токен обновился, а на другой нет? Ведь метод getToken() не проверяет наличие нового токена в localStorage.
    4. Что если при истекшем токене несколько запросов посылаются одновременно? Т. е. в этом случае для каждого из запросов isExpired() вернет false и для запустится обновление токена.
  • MicroSPA, или как изобрести квадратное колесо
    0
    Что-то я вас не понимаю.
    Если вы хотите сделать билд отдельного компонента, то точкой входа будет файл .vue. Такой компонент вы сможете подключить на страницу и использовать во Vue-приложении.
    Если же вы хотите билд готового приложения, то используете как точку входа main.js. Полученный файл вы подключите к странице и он все сделает сам.
  • MicroSPA, или как изобрести квадратное колесо
    0

    Да, но вы вводите людей в заблуждение в статье. А если вы захотите "инициализировать приложения в определенном месте или после какого-то действия", то вам уже не IIFE нужна. Ну а если вебпак это сделает, то нам не надо делать это еще и самим. Прием безусловно хороший, но тут он не нужен.

  • MicroSPA, или как изобрести квадратное колесо
    0

    Если использовать режим сборки библиотеки и в качестве точки входа указать .vue файл, то чем это не отдельный компонент?

  • MicroSPA, или как изобрести квадратное колесо
    0
    Ок. Тогда советую вам использовать Vue CLI если вы еще этого не делаете, у него есть возможность делать сборки отдельных компонентов, можно даже в виде веб-компонентов.

    И еще исправьте, пожалуйста:
    Но в таком случае код сам по себе не выполнится...

    Выполнится, так как этот код уже вызывает функцию, а вы ее зачем-то заворачиваете в другую функцию и вызываете уже ее.
  • MicroSPA, или как изобрести квадратное колесо
    +1
    Прочитав статью, я так и не понял:
    1. Что может дать внедрение frontend-фреймворков в решения на sitefinity?
    2. Почему вы решили использовать именно Vue?

    Ну и вообще я считаю что данные способы требуют доработки, как минимум. Вы используете это в production?
  • Vue.js: Хуки жизненного цикла ваших и сторонних компонентов
    0
    Не думаю, что события порожденные ядром для каждого компонента в вашем приложении не рекомендуются к использованию

    Конечно вы можете их использовать, но разработчики оставляют за собой право в любой момент убрать их, переименовать или изменить логику их работы. Это конечно не критично, но надо об этом помнить. Подобных «скрытых» возможностей во Vue много и Эван сам писал что лучше воздержаться от использования их в коде. Например вот он пишет про использование _uid.

    ну и из приведенного вами пункта документации можно, вывести что компонент порождает событие hook: имя_хука_жизненного_цикла, но вот о том что его можно подслушать на компоненте, увы не сказано

    1. Компонент порождает события «hook:».
    2. События компонента можно слушать.
    Неужели вам надо сказать это еще более явно? )
  • Vue.js: Хуки жизненного цикла ваших и сторонних компонентов
    +1
    Ну почему же ни слова. Пара слов есть. )
    vuejs.org/v2/guide/components-edge-cases.html#Programmatic-Event-Listeners

    А вообще то — чего нет в документации — это обычно возможности, которые не рекомендуется использовать, потому что они могут исчезнуть или измениться в очередной версии.
  • Быстрый поиск источника нежелательных мутаций свойства объекта
    +3
    Другие специалисты JavaScript просто не засоряют глобальное пространство имен.
  • Dap в действии. Пишем TodoMVC. Часть 1
    0
    Насколько я вижу js у вас только под капотом. А используя Dap надо писать строки текста на каком-то другом языке и передавать их в функции.
  • Dap в действии. Пишем TodoMVC. Часть 1
    +3

    Уверенности в себе вам не занимать. )

  • Dap в действии. Пишем TodoMVC. Часть 1
    0
    Это очень сильно похоже на то, во что компилируется JSX или шаблоны Vue, только хуже.
    ru.vuejs.org/v2/guide/render-function.html
  • Vue Storefront: Второй подход к снаряду
    0
    Ну если на какой-то лекции так говорили — значит так оно и есть. Автор, удаляй статью.
  • CSS-переход свойства height от 0px до auto
    +2
    Спасибо, интересное решение. Но весь смысл статьи теряется из-за, того что вы не объясняете зачем тут вообще нужна строка:
    window.getComputedStyle(elBlock, null).getPropertyValue("height");

    Было бы очень полезно если бы вы это описали. Кстати эту строку можно заменить на эту:
    elBlock.clientHeight;
  • 12 концепций JavaScript, о которых нужно знать
    0
    Методы find(), findIndexOf() и indexOf()

    В JS нет метода findIndexOf().

  • Vuex — чрезмерное использование геттеров в приложении. Разбор ошибки
    0

    Насчет увеличения связности...


    При использовании mapState, вам надо знать о структуре данных в модуле ровно столько же, сколько и при использовании mapGetters. Если я не прав — приведите пример в котором это не так.

  • Vuex — чрезмерное использование геттеров в приложении. Разбор ошибки
    0

    Насчет увеличения объема кода...


    Вы немного лукавите приводя примеры кода.
    Я имею ввиду что если использовать геттеры для каждого куска состояния, то код увеличивается, прежде всего, в хранилище. И с этим уж никто не поспорит, так как это очевидно и я даже пример приводить не буду.


    Но в ваших примерах вы приводите также код из компонента. Давайте рассмотрим несколько вариантов:


    Вариант 1:
    Допустим я не использую mapState и mapGetters. Тогда объем кода в компоненте для меня не меняется так как я в любом случае создаю вычисляемое свойство и в нем одной строкой возвращаю состояние хоть из стейта, хоть из геттера:


    // Без геттера users()
    users() {
      return this.$store.state.users;
    },
    
    // С геттером users()
    users() {
      return this.$store.getters.users;
    },

    Тут объем кода одинаков (на самом деле нет — не используя геттер мы сэкономим 2 символа, но это мелочи).


    Вариант 2:
    Допустим я использую mapState и mapGetters.


    // Без геттера users()
    ...mapState([
      'users'
    ]),
    
    // С геттером users()
    ...mapGetters([
      'users'
    ]),

    Снова не вижу разницы.


    Тут вы наверное заметите что я вас обманул, так как не использую и mapState, и mapGetters одновременно. Что ж — вы правы, если использовать их вместе, то код в компоненте увеличится:


    // Без геттера users()
    ...mapState([
      'users'
    ]),
    ...mapGetters([
      'articles',
      'comments'
    ]),
    
    // С геттером users()
    ...mapGetters([
      'users',
      'articles',
      'comments'
    ]),

    Но должен сказать что эти 2 лишние строчки скорее всего окупятся теми строками, которые вы не напишите в хранилище. И еще по своему опыту могу сказать следующее: так как я не пишу геттеры для каждого свойства в состоянии, то мне очень (очень очень) редко приходится использовать в компоненте mapState и mapGetters одновременно. А значит и в последнем случае — я не получу выгоды от вашего подхода.

  • Vuex — чрезмерное использование геттеров в приложении. Разбор ошибки
    0

    Если я неправильно понял и имелось ввиду, то о чем вы говорите то дополню:


    Если после изменения структуры хранилища те данные которые были не производными — стали производными, то надо добавить геттер для них и это не будет противоречить тому что написано в статье. Но не стоит добавлять геттеры для всех данных "по умолчанию".


    На самом деле все просто. Эта и множество других, похожих как две капли воды, статей про геттеры Vuex пытаются донести одно простое правило:


    Не надо делать такие геттеры:


    getProp(state) {
      return state.prop;
    }
  • Vuex — чрезмерное использование геттеров в приложении. Разбор ошибки
    0

    Приложение перегружается тем, что это увеличивает объем кода. И на связность это никак не влияет, потому что такие геттеры попросту отдают состояние. В общем геттер вида:


    getUser(state) {
      return state.user;
    }

    Это просто лишний кусок кода и лишний вызов функции при работе приложения. Не то чтобы он сильно нагружает приложение, но и ценности никакой не имеет.

  • Vuex — чрезмерное использование геттеров в приложении. Разбор ошибки
    0

    Вы не правы.
    Если формат данных меняется, то надо приводить данные к нужному формату еще на входе.
    Например API возвращал объект в одном формате:


    let user = {
      "name": "Вася",
      "sex": "male",
      "image": "https://site.ru/img/vasya.png"
    };

    А потом стал возвращать в другом:


    let rawUser = {
      "login": "Вася",
      "male": true,
      "avatar": "/img/vasya.png"
    };

    То не надо пихать его в хранилище в таком виде в каком он пришел. Надо сразу же в обработчике результата запроса или в экшене или, на худой конец, в мутации привести объект к такому формату с которым ваше приложение привыкло работать:


    let user = {
      "name": rawUser.login,
      "sex": rawUser.male ? "male" : "female",
      "image": "https://site.ru" + rawUser.avatar
    };

    И только после этого сохранять его в состоянии.
    А откладывать преобразование формата на самый последний момент (в геттер) — это по прежнему не правильно. Геттеры нужны только для того чтобы вычислять производное состояние на основе состояния хранилища. Т. е. это практически то же самое, что computed в компонентах.

  • Анонимный Дед Мороз 2018-2019: пост хвастовства новогодними подарками
    +10
    Мне повезло с Дедом Морозом, он быстро отправил подарок и поделился трек-номером, чтобы я его не пропустил. )

    Но главное что он удачно выбрал подарок, так как я буквально на этой неделе решил запилить какое-нибудь приложение для управления гаджетами по Bluetooth и искал себе подопытное устройство. )

    Но пусть мой Дед не переживает — я обещаю не переусердствовать с экспериментами и даже буду использовать подарок по прямому назначению так как портативной колонки у меня до этого не было, а вещь действительно нужная.

    А еще в комплекте идут прикольные наклейки и душевное письмо. )))

    Дед Мороз, спасибо тебе ОГРОМНОЕ!!!

    Собственно сам подарок
    image
  • Введение в SOLID: новый редецентрализованный интернет Тима Бернерса-Ли
    0
    Turtle is a compact way of representing RDF data, using URLs to represent subject, predicate and object.

    Чуть чуть недоперевели.
  • Советы по CSS, которые вы вряд ли найдете в самоучителях
    0
    Спасибо. content-box это в моем понимании и есть «доступное пространство», просто не знал как его правильно обозвать.
  • Советы по CSS, которые вы вряд ли найдете в самоучителях
    0
    И если уж быть совсем точным, то padding-top считается не от ширины родителя, а от ширины доступного пространства. Т. е. если у родительского блока стоит box-sizing: border-box; и есть padding или border, то их размеры вычитаются из той ширины от которой считается padding-top и т. п.
  • Советы по CSS, которые вы вряд ли найдете в самоучителях
    +4
    Оно устанавливает параметры относительно родительской высоты. Вам нужна демонстрация?

    Не высоты, а ширины.

    Если вы так сделаете, браузер заметит три смежных поля и захочет объединить их в один большой блок.

    Результат будет выглядеть так:
    image

    Не совсем так. За отступ берется не сумма а максимальное значение из Margin 1, Margin 2 и Margin 3.

    Если вы работали с CSS много лет и никогда не встречались с этой проблемой, то это потому, что отступы объединяются только когда:
    • ...
    • свойство overflow отличается от «initial»;
    • ...


    Наоборот. Не отличается от initial, а равно initial. Или visible.
  • Личный опыт: от идеи и чистого листа до черновой версии сайта
    0

    Спасибо, за статью. Местами я даже понимал что иногда чувствую то же самое что и вы, хоть я и работаю программистом уже очень давно. Старайтесь довести свой проект до конца, потому что я считаю это самой трудной задачей. Особенно трудно заставить себя что-то доделать, когда осталось совсем немного. Если нужна будет помощь — обращайтесь. С питоном я знаком мало, но с фронтендом помогу по возможности.

  • Освоение Vuex — с нуля до героя
    +1
    Ну во первых изменение состояние Vuex автоматически вызывает изменения в DOM, а в LocalStorage отследить состояние можно только отследив событие «storage», причем это событие не сработает если оно вызвано кодом исполняемым в той же вкладке.

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

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

    Ну и еще много причин. Если в кратце — то это разные механизмы, предназначенные для разных задач и заменить одно другим нельзя.
  • Освоение Vuex — с нуля до героя
    0
    Геттеры используются для доступа к значениям, находящимся в хранилище.
    Даже в официальной документации Vuex сказано что геттеры следует использовать только для производных данных, основанных на состоянии.
  • Освоение Vuex — с нуля до героя
    0
    В коде из раздела «Но почему?» ошибка в действии «SET_NAME»:

    context.dispatch('SET_NAME', name);

    Тут должно быть не dispatch, a commit — иначе получается какая-то рекурсия.

  • Странные операторы в PHP
    +3
    Ну, например, вы понимаете смысл следующих строк?
    Просто добавьте b перед любой строкой, но это ничего сделает, словно строка обычным образом.
    Он работает так, вы ожидаете, то есть добавляя элемент с правой части в левую частью массива.
    И просто прочтите остальной текст — сами все увидите.

    Насчет снятия с публикации — решайте сами. Я бы постарался довести перевод до нормального состояния.
  • Странные операторы в PHP
    +1
    Очень крутой стеб. ))) Не сразу понял в чем подвох.
    Жаль только качество перевода оставляет желать лучшего. Исправьте хотя бы явные орфографические ошибки.
  • Типографика и современный CSS
    0
    Точно. ) Что-то у меня переклинило.
  • Типографика и современный CSS
    +1
    А в чем проблема? Есть псевдоселектор :lang для этого:

    p:lang(ru) {
      quotes: "«" "»" "„" "“";
    }
    p:lang(en) {
      quotes: "“" "”" "‘" "’";
    }

    Живой пример