Сервисная архитектура во Vue 2 | Веб-студия Nat.od.ua
Сервисная архитектура во Vue 2
Да-да, я знаю, Vue 3 находится в stable-версии, и даже Nuxt наконец-то обновился. Но именно 3-й Vue с его provider / inject подтколкнул меня к поиску решения о том, как можно удобно инкапсулировать бизнес-логику во Vue 2.
Введение
Начнем с вопроса “Почему нельзя просто обновиться до Vue 3?”. Все просто, некоторые проекты обладают таким уровнем связанности с другими проектами, что это невозможно сделать быстро. Где-то возможно используются специфичные пакеты, которые были написаны только под 2-ю версию Vue. Где-то разработчиков устраивает Vue 2, а даже если бы они и перешли на Vue 3, они продолжали бы писать на Options API (скажу сразу, я не проверяла свое решение на Vue 3, так что не уверена сработает ли такой подход там, но вообще должен).
Как можно инкапсулировать логику
На просторах интернета и участвуя в вопросах, задаваемых в чатах (по типу “Vue.js – русскоговорящее сообщество”), да и просто работая, чаще всего я видела несколько решений. Давайте разберем их плюсы и минусы.
Вынести во Vuex/Pinia/Другой стейт менеджер
На удивление один из самых популярных ответов, как только нужно делиться какими-то данными – вынеси в стор.
Доходит до смешного, человек спрашивал как можно передать строку поиска из компонента в соседний (у них общий родитель). Ему накинули несколько решений, и человек выбрал Vuex, потому что на его взгляд это проще.
Другой пример, на проекте я видела страницу, которая сохраняла временные данные форм (и в какой-то мере кешировала на сессию) с помощью.. Vuex. Я думаю, нет смысла объяснять подробно чем это чревато, но багов там связанных с этим было много, мне пришлось полностью переделать эту страницу.
Pros
-
Часто советуют, легко найти помощь
-
Использование vuex интуитивно понятно
-
Возможно внушает чувство безопасности
-
В целом легко читается, понятно откуда приходят данные
-
Можно получить только те данные, которые тебе нужны в конкретном компоненте
Cons
-
Вызывает баги, если пытаться хранить временные данные (которые должны чиститься, или меняться в зависимости от контекста)
-
Невозможно переиспользовать логику (модуль один на сайт, от этого ты никуда не денешься, дополнительный экземпляр не создашь) только если не сделать 10 одинаковых модулей
-
Используя недолго эту логику, она все равно останется в памяти, хоть и больше не требуется
-
Данные не защищены, любой компонент может изменить их с помощью прямого обращения к state
Миксины
Это второй по популярности метод выноса какой-то общей логики, но если ответ про Vuex частый при проблеме распространения данных, то миксины – это популярный метод выноса логики. Хотя по моим впечатлениям люди начали реже им пользоваться, в силу того что в официальной библиотеке рекомендуют максимально остерегаться этого способа.
Pros
-
опять же интуитивно понятно, выглядит как кусок компонента
-
другого способа интегрировать общий хук, или фреймворко-зависимые элементы особо нет
Cons
-
Если само написание миксина действительно интуитивно понятно, то вот чтение компонента, использующего миксин совершенно нечитабельно. Ты выделяешь переменную, ищешь ее по файлу, а ее просто нет, и вот эту маленькую строчку mixins очень легко пропустить.
-
Легко затереть функциональность миксина, используя случайно те же имена свойств/методов
-
Иногда миксины используют свойства, которые должны быть определены в компоненте, а ты можешь этого не знать
-
Невозможно расшарить данные (только если не положить их во vuex)
-
Подходит только для переиспользования кода, что-то глобальное сделать с помощью миксина не получится
-
Выбрать какие методы/свойства тебе нужны нельзя
Provide / Inject
Это уже не самый популярный способ, не все знают про эту опцию. Многие знают про то, что это есть во Vue 3, но во Vue 2 provide появился еще в версии 2.2.0. Подробнее можно почитать по ссылке.
В целом технология позволяет передать либо объект, либо функцию, возвращающую объект. Так что думаю есть возможность, если поиграться передать тот же экземпляр класса. Но возможно это вызовет определенные проблемы.
Pros
-
Позволяет передавать данные на любую глубину
-
Можно выбрать, что ты будешь инъектить
Cons
-
Требует общего родителя, в худшем случае придется делать это на странице или в App что засоряет код
-
Таким образом не получится переиспользовать код, это больше про распространение данных
-
Если сделать экземпляр класса (каким-то образом, я не пробовала), то ты его себе заберешь целиком, нет возможности выбрать, что тебе надо
-
Не интуитивно и не очевидно, что будет происходить с реактивностью, где менять эти данные, и вообще вызывает много вопросов
Почему я упомянула provide/inject в начале
Когда я писала на Vue 2, у меня даже примерной идеи не было, как бы можно было инкапсулировать логику. Мне казалось, что в том формате, как мы делаем компоненты, это будет по-любому неудобно, непонятно, и как-то костыльно.
Vue 3 с Composition API открыл для меня новую веху, там можно сделать экземпляр класса, полностью обернуть его в reactive, сделать provide прям на этапе создания приложения (т.е. в index.js условном, что было понятно).
Но и это решение меня не до конца устраивало, мне хотелось сделать это как-то по-другому. Пока я об этом думала, я перешла на другой проект, который написан на Vue 2, и это подтолкнуло меня к поиску решения.
Вынести в функции
Этот способ очень хорошо подходит для простых функций, не связанных ни с чем другим, валидаторы или форматтеры. С точки зрения инкапсуляции логики (а обычно в таком случае мы говорим про связный процесс, где происходит несколько этапов в разное время) это не самый подходящий способ.
Pros
-
Легко использовать, импортируешь функцию и используешь
-
Знакомо и узнаваемо
Cons
-
Для связанного процесса приходится передавать данные из одной функции в другую, что ухудшает читабельность
-
Если пытаешься сохранить данные в какой-то переменной вне функций, не будет ясности, что там находится
Глобальные переменные
Во Vue 2 я частенько записывала созданный мной класс, хранящий экземпляр Axios, в глобальные переменные. Это довольно удобно для модуля, который используется повсеместно.
Pros
-
Удобное использование через this
-
Можно в глобальную переменную записать экземпляр класса, что увеличивает ваши возможности
Cons
-
Даже если записать экземпляр класса, то он будет один
-
Непонятно, будут ли данные реактивными, не совсем очевидно
-
Использование через this удобно для тех, кто знает, какие данные в проекте глобальные. Для остальных придется еще догадаться, где искать эту запись, и что же кроется под переменной.
Вынести в класс
Кажется самым удобным методом, но те статьи, которые я находила, предлагали либо сделать singleton, либо делать статические методы и встраивать их подобным образом
methods: {
someAlias() {
Class.someMethodFromClass();
}
}
Такой способ мне не нравится тем, что много мусорных функций, нет понимания как встраивать данные и менять их. Да и вообще так получилось, что я не нашла ни одной статьи, которая бы показывала полноценное решение, учитывая всевозможные случаи.
Поэтому я решила создать это решение сама.
Вводные
Хочется, чтобы можно было создать сервис, который
-
Создавал экземпляр только по запросу, позволял создать несколько экземпляров, мог удалить нужный экземпляр
-
Было понятно откуда пришли данные или методы, чтобы при поиске по файлу названия можно было найти источник
-
Данные должны быть консистентные, при изменении в одном месте, во всех остальных местах они должны стать такими же
-
Если данные используются в компоненте, то должна быть возможность сделать их реактивными, то есть при отображении в template после изменения компонент должен перерендериться
-
Должна быть возможность защитить данные, чтобы менять их можно было только из класса, запретить изменение из компонентов
-
Должна быть возможность менять данные с компонента, установить валидатор для подобных изменений
-
Должна быть возможность получить экземпляр компонента для каких-то специфичных действий, хоть я и не очень это поддерживаю
-
Должна быть возможность встраивать этот класс в любой компонент без обязательства иметь общего родителя
Спойлер
Я смогла реализовать подобную логику, оказалось, это было так просто, что даже смешно. И теперь я хочу рассказать об этом вам и предоставить функции-фабрики для обвязки подобного класса, чтобы вы могли тоже удобно пользоваться классами.
Это 1 часть статьи про реализацию сервиса во Vue 2.
Во 2 части я хочу рассказать о деталях проектирования класса, как работать с разными типами данных, каким образом они встраиваются в компонент и приобретают реактивность, как сделать геттер на свойство/свойства (аналог computed) и передать его в компонент.
В 3 части я расскажу про экземпляры, как регулировать создание и уничтожение, покажу мои функции-фабрики для обвязки класса, как сделать удобную передачу таких свойств в компонент.
Опционально
В 4 части я бы хотела порассуждать о том, какой сервис можно считать хорошим, что стоит выносить в сервис, чтобы не выстрелить себе потом в ногу, как их тестировать и как тестировать компоненты, использующие сервис.
Буду смотреть по вашей реакции, будет ли вам интересно про это прочитать.
Если не хотите ждать, то вот ссылка на репозиторий с рабочим решением, там есть подробные комментарии о реализации. Наиболее интересные файлы: сам класс, и конечно функции для обвязки.
Этот вариант еще в стадии черновика, я готовлю для него документацию. С практикой я буду его дорабатывать, плюс по ходу написания следующих частей я могу вспомнить про какой-то кейс, который не учла.
Пользовательские истории в разработке / Хабр | Веб-студия Nat.od.ua
Пользовательские истории в разработке / Хабр
Пользовательская история (User story) описывает тип пользователей, чего они хотят и почему. Этот инструмент помогает создать упрощенное описание требований, но при этом таковым не является. Требования — это другой инструмент, с более сложной структурой и описанием.
Обычно User story используют при разработке по методологии Agile. На этапе дискавери-фазы обычно разбивают разработку продукта на пользовательские истории, а не на характеристики или требования.
Зачем нужны пользовательские истории
Пользовательские истории — это инструмент планирования. С их помощью определяем приоритеты, оцениваем и принимаем решение: на каком этапе (спринте) будет реализована та или иная функциональность.
Сила пользовательских историй в том, что они дают начало диалогу. Вместо того, чтобы просто взять и передать коллегам спецификацию, которая интерпретируется сначала разработчиками, потом тестировщиками — мы начинаем обсуждение. Включаем в коммуникацию сотрудников с различными навыками. И так по каждой новой фиче.
Преимущества пользовательских историй
-
Короткие и понятные. Легко вникнуть каждому участнику процесса.
-
Позволяют разбить проект на небольшие этапы и показывать видимые результаты на каждом спринте.
-
Команда концентрируется на потребностях реальных людей, а не на абстрактных объектах.
-
Позволяют разработчикам и клиентам обсуждать требования на протяжении всей жизни проекта.
-
Подходят для проектов, где требования изменчивы или плохо поняты.
-
Облегчают оценку.
Как выглядит пользовательская история
Большинство команд пользуются шаблоном пользовательской истории, обычно это всего лишь одно или два предложения, написанных по следующей формуле:
Как , я хочу , чтобы .
Детально рассмотрим шаблон:
Описание пользователя. Кем является человек по ту сторону экрана? Личность пользовательской истории не обязательно должна ограничиваться должностью человека. Например, руководителем удаленной команды может быть как и менеджер отдела, так генеральный директор, или любое другое лицо в компании. При построении истории мы должны понимать как думает и работает этот человек, знать его намерения. В идеале у пользователей нужно провести интервью.
Функциональность. Здесь описывается не сама фича, а намерения людей, каких целей они хотят достичь.
Выгода. Для чего пользователи совершают все эти действия? Описываем конечную выгоду и проблемы, которые хочет решить выбранная личность.
Примеры пользовательских историй
На практике пользовательские истории могут выглядеть так:
-
Как администратор базы данных, я хочу автоматически объединять наборы данных из разных источников, чтобы мне было проще создавать отчеты для моих внутренних клиентов.
-
Как бренд-менеджер, я хочу получать уведомления всякий раз, когда торговый посредник рекламирует наши продукты по ценам ниже согласованных, чтобы я мог быстро принять меры для защиты нашего бренда.
-
Как руководитель удаленной группы, я хочу, чтобы в наше приложение для обмена сообщениями для команды было включено совместное использование файлов и аннотации, чтобы моя команда могла сотрудничать в режиме реального времени и хранить архив своей работы в одном месте.
Важно: Различные пользователи, описанные в историях могут быть одним и тем же человеком, которому для разных задач требуются разные функции.
Почему мы используем User story
Вместо того, чтобы писать планы с точки зрения продукта (какие функции нужно создать), User stories разворачивают нас к пользователям. Этот инструмент заставляет составлять каждую предложенную идею для новой функциональности с точки зрения реальных людей, которые будут использовать эту функциональность.Таким образом, мы создаем лучший интерфейс для пользователей будущего продукта.
Также применение пользовательских историй сокращает затраты времени и бюджет на создание исчерпывающей документации, делает работу проще и понятнее.
Как сделать динамические цвета в CSS / Хабр | Веб-студия Nat.od.ua
Как сделать динамические цвета в CSS / Хабр
Когда говорим «динамический», подразумеваем JavaScript. Но некоторые динамические функции можно реализовать, используя только CSS. Например, цвета.
С помощью прозрачности
Возможно, вы уже знаете, как создавать цвета с помощью пользовательских свойств CSS и альфа-канала. Освежим память:
:root {
–color: 255 255 0;
}
.selector {
background-color: rgb(var(–color) / 0.5);
}
Код выше — самый простой для создания пользовательских свойств цвета, но несовершенный. Нужно определить свойство color в цветовом пространстве, которое поддерживает альфа-канал: rgb(), rgba(), hsla().
:root {
–color-rgb: 255 255 0;
–color-hsl: 5 30% 20%;
}
.selector {
background-color: rgb(var(–color-rgb) / 0.5);
background-color: hsl(var(–color-hsl) / 0.5);
}
Таким образом, вы не переключать значение цвета пользовательского свойства с одного типа на другой. Обычно про такое пишут в JavaScript, там используется приведение типов. Но вот как это выглядит в CSS:
:root {
–color: #fa0000;
}
.selector {
/*
Trying to convert a HEX color to an RGB one doesn’t work
This snippet will not work. this just return a blank white background
*/
background-color: rgb(var(–color) / 0.5);
}
С учётом сказанного, на самом деле невозможно использовать значения цветов HEX для динамических цветов в CSS. Даже указать альфа-канал для цвета HEX, как #FA000060, можно только декларативно, ведь в CSS нет конкатенации:
:root {
–color: #fa0000;
}
.selector {
/* You can’t dynamically specify the alpha channel. This will still not do anything */
background-color: var(–color) + “60”;
}
Можно объявить значение пользовательского свойства, используя любой цветовой тип: rgb, rgba, hsla, hsl, hex. И уже этот тип с лёгкостью преобразуется в любой другой. Пример управления динамическими цветами:
/* – – – – – – – – – – – – Using hex Colors – – – – – – – – – – – – – – */
:root {
–color: #fa0000;
}
.selector {
/* can’t do this */
background-color: rgb(var(–color) / 0.5);
/* can do this */
background-color: rgb(from var(–color) r g b / .5);
}
Если следовать синтаксису в строке 7, то ничего не получится. Правильный синтаксис в девятой строке показывает, как создавать динамические цвета и управлять ими. Вот как это выглядит, если попытаться использовать именованные цвета:
/* – – – – – – – – – – – – Using Named Colors – – – – – – – – – – – – – – */
:root {
–color: red;
}
.selector {
background-color: rgb(from var(–color) r g b / .5);
}С помощью функции calc()
У работы с динамическими цветами через альфа-канал есть свои недостатки: прозрачные цвета не всегда смешиваются с белым, вместо этого сливаются с цветами, на которых расположены. То есть если вам нужна более светлая версия цвета, вы можете изменить альфа-канал, но изменение будет неоднородным. В некоторых местах на странице на новую версию повлияют те цвета, на которых расположены прозрачные. Чтобы ликвидировать это влияние, надо использовать непрозрачные цвета. В CSS можно определить пользовательские свойства и каналы индивидуально:
:root {
/* Define individual channels of a specific color */
–color-h: 0;
–color-s: 100%;
–color-l: 50%;
}
.selector {
/* Dynamically change individual channels */
color: hsl(
var(–color-h),
calc(var(–color-s) – 10%),
var(–color-l)
);
}
Но от этого код удлиняется, а значения HEX всё равно не поддерживаются. Решение — функция calc():
:root {
–color: #ff0000;
}
.selector {
color: hsl(from var(–color) h calc(s – 10%) l);
}С помощью значения фильтра
Функция filter: brightness(x%) динамически изменяет значения цвета в процентах. Минус метода в том, что функция влияет на конкретный элемент. То есть некоторые части страницы могут отличаться друг от друга.
Не надо залезать в JavaScript, чтобы управлять динамическими цветами на минималках, когда вы делаете тёмный режим или меняете цвет при движении мышки. Пользуйтесь маленькими трюками CSS.
Как мы провели второй русскоязычный Laravel-митап / Хабр | Веб-студия Nat.od.ua
Как мы провели второй русскоязычный Laravel-митап / Хабр
Привет, за клавиатурой Миша Радионов, и я снова расскажу вам про Laravel. Нет, не про тонкости этого фреймворка, а про Laravel-митап, который мы провели в Студии Флаг уже во второй раз.
Немного истории
За 12 лет существования компании мы прошли разные этапы. Но так или иначе мы пришли к одной мысли — нужно развивать узкий стек технологий, и стать в нем лучшими. Так и произошло с Laravel. Мы постоянно записываем и выкладываем курсы по Laravel на Youtube и делимся пакетами в Open Source. У нас больше десятка бэкендеров, которые пишут только на Laravel, и за это время реализовали более сотни успешных проектов на этом фреймворке.
Так, однажды встал вопрос, а почему бы нам не делиться нашей экспертностью и не проводить Laravel-митап. И вот, год назад, прошел первый митап, в котором выступали в качестве докладчиков наши ребята. Подробнее о первом митапе мы уже писали в блоге. Читайте тут.
Рецепт хорошего митапа
Что вообще такое митап? Митап — это неформальная встреча айтишников для обсуждения рабочих вопросов и обмена опытом. По сути, это — конференция со спикерами, но в более расслабленном формате. Перед нами стояла задача подготовить не только полезное и информативное мероприятие, но и драйвовое, чтобы соскучившиеся айтишники точно смогли оттянуться.
Для начала мы продумали и сделали яркий и цепляющий лендинг, на котором разметили всю нужную информацию, таймлайн и ФОС как для спикеров, так и для зрителей.
Через какое время мы начали получать заявки от спикеров. Один из них откликнулся с Кемеровской области, и был намерен приехать в Екатеринбург ради такого события 🙂 Тогда мы уже поняли, что второй Laravel-митап пройдет на высоком уровне.
Мы начали работать со спикерами, помогать с докладами, оттачивать презентации. Параллельно с этим встал вопрос: чем кормить и поить зрителей. Конечно же, пивом и пиццей. Пицца у нас была от Додо Пиццы, которые выступили в качестве партнера мероприятия. А вот пиво мы заказали от Jaws.
А что делать зрителям в перерывах? Ну конечно общаться со спикерами и играть в кикер. Для чего еще у нас в офисе стоят 4 стола для кикера. Еще мы намутили классного фотографа, который поймал все яркие моменты митапа.
Это что касается подготовки, так а что по спикерам в этом году? Сейчас расскажу про каждый доклад.
Доклад 1. Сергей Сахаров — «Использование пакета Laravel Octane для ускорения работы приложения».
Сергей приехал на митап с города Юрга, Кемеровская область. Как он рассказывает, только увидел анонс, и не раздумывая, купил билеты. И Екатеринбург посетил, и полезным опытом с коллегами поделился 🙂
В своем докладе Сергей рассказал о плюсах и минусах пакета Laravel Octane, особенностях работы, нюансах, которые стоит учитывать при переводе существующего приложения на этот пакет с примерами из практики.
Вот, что Сергей сказал о нашем митапе.
Спасибо за митап и за тёплый приём! После митапа остались только положительные эмоции. У Студии Флаг классная команда профессионалов, которой желаю лёгкого достижения любых целей и вывести Laravel-митап на уровень не ниже Laracon’a 🙂
Доклад 2. Роман Постников — «Laravel + Clean Architecture».
Роман когда-то работал в нашей студии и также выступал спикером на прошлом митапе. В этом году Роман поделился главным принципом «Чистой архитектуры» и рассказал, как вынести весь фреймворк на внешний слой, от которого не будет зависеть бизнес-логика приложения. Такое решение поможет легко тестировать и поддерживать даже самое большое приложение.
Доклад 3. Максим Колмогоров — «Внедряем SSR в проект».
Максим рассказал про технологию SSR и способы ее внедрения в Laravel проект через готовый плагин, или с помощью SSR-фреймворков. Его доклад отметился бурным обсуждением и запомнился шутками и интересной подачей материала Максимом.
Классное мероприятие, прихожу второй раз. Остался очень доволен. Приду третий раз, даже снова выступлю, если позовут. Вообще, у нас в России IT митапы очень извращены всякими штуками по типу: HR, которые навязывают вакансии, тонна ненужной рекламы курсов, некомпетентные спикеры и тому подобное. Здесь все было иначе: программисты собрались и веселятся. Настоящая IT тусовка для своих. Очень рад, что знаком с организаторами, и меня позвали. От себя лишь постарался притащить на мероприятие всех моих знакомых. К слову, они тоже не пожалели, что пришли.
Доклад 4. Алексей Смирнов — «Мутационное тестирование».
Алексей — единственный докладчик от нашей студии. Это сильный и опытный разработчик, который также выступал на митапе в прошлом году.
Для проверки корректной работы кода используются автотесты. Их количество растёт, проект становится проще поддерживать. Но когда тестов в проекте уже достаточно, высокое покрытие может ввести в заблуждение и дать ложные надежды, что всё хорошо протестировано, и разного рода изменения ничего не сломают. Но это не так. В своем докладе Алексей рассказал о том, как избежать проскакивание багов мимо тестов, проверить сами тесты на качество, и при чём тут мутационное тестирование.
Что еще интересного было на митапе
Митап прошел здорово. В нашем офисе собралось около 70 зрителей, а для тех, кто не смог приехать, мы организовали онлайн-трансляцию на YouTube.
Между докладами спикеров зрители активно общались и обменивались опытом. Кто-то устроил мини-турнир по кикеру, а кто-то решил провести пару свободных минут, играя классические композиции на фортепиано. Было видно, что айтишники за время локдауна и удаленки истосковались по нетворкингу и живому общению. Мы продумали все развлечения так, чтобы каждый участник провел перерывы максимально продуктивно и интересно.
В середине мероприятия был организован большой перерыв с пивом и пиццей, во время которого зрители и спикеры завязали новые знакомства, обсудили Laravel и не только.
Завершился митап афтерпати, на которое остались все желающие. После организаторы получили обратную связь, которая мотивирует их на проведение новых, крутых мероприятий для айтишников.
Отзывы зрителей
После митапа мы, конечно же, собрали обратную связь, чтобы в следующий раз было еще круче. Вот некоторые из отзывов, которые нам прилетели.
Спасибо организаторам, что смогли провести такое мероприятие. Это очень радует.
Ведущий огонь! Неформально, просто, весело! Шутейки с интеграционной рекламой хороши! А если серьёзно, доклады на этот раз очень понятные, без занудства, жаль не удалось наших фронтендеров притащить на этот митап
Организация мне понравилась. Доклады не сильно длинные, без лишней воды, как раз чтобы получить необходимое представления о технологии для дальнейшего изучения. Юмор, юмор всегда располагает
Заключение
Такая крутая обратная связь мотивирует нас на проведение еще больших и качественных ивентов. Конечно, мы и дальше продолжим проводить Laravel-митапы, но в планах у нас появились новые идеи, о которых я вам пока рассказывать не буду 🤫
Смотрите онлайн-трансляцию митапа, ставьте лайки и оставляйте комментарии.
Отображаем ACF поля красиво и без кодинга / Хабр | Веб-студия Nat.od.ua
Отображаем ACF поля красиво и без кодинга / Хабр
Плагин Advanced Custom Fields используется в WordPress повсеместно, за свою карьеру я встретил лишь несколько сайтов которые обходились без него (весьма специфические). Большой набор типов полей, хороший интерфейс для админов, обширная документация для разработчиков. Казалось бы, чего проще, вывести поля на фронт сайта. Но на практике это делается довольно некрасиво, и занимает гораздо больше времени, чем можно было бы ожидать. Я расскажу как вывести любые ACF поля на фронт без кодинга (и без visual page builders), очень быстро и не превращая код темы в черную дыру спагетти код.
Проблемы кодинга
Самый простой пример – вывод поля. Казалось бы, что может быть проще? Но в процессе разработки “всплывают” проблемы.
Проблема №1. Постоянное посещение ACF группы в админке
Во первых это имя поля. По названию (label) далеко не всегда (а на практике – никогда) можно узнать имя поля, и каждый раз приходится идти в список групп, находить текущую и смотреть имя поля. Ладно, с этим мы разобрались. Теперь что по поводу возвращаемого значения? Хорошо если мы говорим про текстовое поле. А если это изображение, select или post? А тут у нас оказывается полный зоопарк, кроме того что у нас есть множество типов (это же хорошо) у каждого типа есть разные return_format-ы. А это значит что нужно в той же группе проверять настройки конкретного поля. Хорошо если возвращается ID или объект (WP_Post). А если массив? (например опция изображения). Какие там ключи? Конечно, когда выводишь ACF поля ежедневно, их имена всегда в памяти, а если был занят другим?
Проблема №2. Постоянное посещение ACF документации
Таким образом мы подходим ко второй проблеме. Чтобы узнать детали return_format-а, ключи возвращаемого массива или как получить label поля вместе со значением приходится часто наведываться в ACF документацию для соответствующего типа поля. Благо документация хорошая. Но время таки уходит.
Проблема №3. Синхронизация изменений
На практике изменения в существующие поля вносятся гораздо чаще чем можно предположить. Например изменяется return_format (не говоря уже про имя и тип поля, и такое бывает) и приходится делать поиск по всему коду темы, чтобы найти куски кода что получают и используют это поле, так что это становится настоящим кошмаром (и кто-то мог использовать в одном случае двойные кавычки, а кто-то одинарные, и имя то поля может быть кратким и не уникальным, пойди найти всех).
Проблема №4 (Опциональная). Спагетти код
Чего только тут мои глаза не видели. Особенно когда вносятся правки, а не создается страница с нуля. Про кучу спагетти кода в шаблонах, где нельзя понять (даже при большом желании) где начало и где конец я просто не упоминаю. В лучшем случае разработчик прямо в functions.php добавляет регистрацию шорткода и в нем делает вывод нужных полей, и далее устанавливает шорткод в нужное место. (И откровенно говоря, когда вносишь правки в такие “веселые” темы, нет ни времени ни желания что либо менять, просто рядом создаешь еще один и стараешься забыть поскорее все что ты видел) Проблема с таким functions.php что в один день это становится файлом в 3-7 тысяч строк кода, без структуры, без начало и конца. И совсем не понятно, зачем нужен определенный кусок кода, где это используется. Про последствия такого подхода я умолчу, думаю ужасы редактирования, отладки и оптимизации всплывут у всех видевших подобное.
Проблема №5. Стилизация и CSS конфликты
Разметка полей обычно делается на скорую руку и классы в разметке используются из тех, что первые приходят на ум. (К сожалению про BEM слышали далеко не все, а используют еще меньше). В худшем случае стили для этих полей будут добавлены глобально, в лучшем только для целевой страницы. В первом случае будет проблема неиспользуемого CSS кода (привет нулевой Google Page Speed) и конфликтов с другими элементами (названия классов то общие), во втором – проблема переиспользования на других страницах.
Суммируя вышесказанное
Эти проблемы замедляют время разработки и внезапно, чтобы вывести 4 поля у разработчика уходит не 1 минута, а 10, и кроме созданного вывода также создаются множество проблем для того, кто это будет править/поддерживать.
Решение. Вывод полей без кодинга с помощью шорткодов
Как же обойти эти проблемы? Речь сейчас пойдет не про встроенные шорткоды. К сожалению они подходят только для примитивных полей (строка, число) и кроме того они выводят только значения, разметку по прежнему надо создавать самим.
Речь про новый (и бесплатный) ACF Views плагин, который предоставляет шорткоды для вывода полей. И если первое что вам пришло в голову – шорткод для вывода значения по имени поля – вы ошиблись.
ACF Views плагин позволяет вам создавать Views (внутри обычные CPT items) в которых вы:
-
Выбираете ACF поле для вывода
(одно или несколько, можно с разных групп. Выбор через обычный select) -
Сохраняете View, копируете шорткод
(из серии ) -
Используете шорткод где угодно
(Выбранные поля должны быть заполнены на том объекте, где устанавливается шорткод, будь то страница или CPT объект. Или нужно использовать object-id аргумент шорткода, чтобы указать id объекта, откуда брать эти поля)
Во время выполнения шорткод будет обработан плагином, и заменен HTML разметкой, которая будет сгенерированна (автоматически) в зависимости от типа поля и значения поля. (Плагин поддерживает все типы полей, включая изображния и select-ы) Это упрощает задачу в разы, и решает вышеупомянутые проблемы:
Проблема №1. Постоянное посещение ACF группы в админке
Вы выбираете поле (или поля) из списка, не нужно искать имя, не нужно заботится о типе и return-format-е.
Проблема №2. Постоянное посещение ACF документации
Плагин автоматически генерирует разметку для полей в зависимости от типа и return-format-а полей, нам заботиться об этом больше не нужно.
Проблема №3. Синхронизация изменений
Плагин сохраняет id выбранных полей и получает информацию о полях от ACF динамически. Это значит что мы можем менять поле как угодно, включая имя и тип, не говоря про return-format и абсолютно никаких обновлений от нас не потребуется. Разметка будет всегда актуальной.
Проблема №4 (Опциональная). Спагетти код
Теперь никакого хаоса в functions.php. Отдельный пункт меню в WordPress админке со списком всех View (вы можете задавать им имена и краткие описания), с поиском по ним.
Проблема №5. Стилизация и CSS конфликты
Теперь это мой любый пункт. Разметка генерируется в BEM стиле, так что больше никаких конфликтов. Кроме этого, каждое View имеет свое поле для CSS кода, где вы можете написать стили для этих полей. Этот CSS: a) никогда не создаст конфликтов (BEM стиль + используется id этой View) b) появляется только на страницах где используется текущая View, так что никаких глобальных стилей.
Суммируя вышесказанное
Используя ACF Views плагин (бесплатный) можно вывести любые ACF поля на фронт очень быстро и не создавая проблем для того, кто это будет править/поддерживать. Подробнее узнать о плагине можно на его официальном сайте, где вы сможете найти ссылку на их YouTube канал, который наглядно демонстрирует использование плагина.
У опытных разработчиков наверняка возникнет вопрос, а что по накладным расходам? Это обертка и вероятно это гораздо медленнее чем обычный код. А вот и нет. Авторы плагина уделили особое внимание вопросам производительности (например использовали JSON в вместо мета полей для хранения Views данных) и даже опубликовали тест, который показывает что разницу с кодом будет невозможно заметить на глаз.
Ниже я привожу несколько скриншотов плагина которые я сделал, чтобы вы могли увидеть, как выглядит UI плагина. Надеюсь эта статья была полезной для вас.
P.S. Функциональность данного плагина выходит за рамки этой статьи. Если вам будет интересно, то я расскажу что еще можно сделать используя данный плагин. (Например выбирать и отображать посты, к примеру отобразить 4 последних WooCoomerce продукта без кодинга)
Оцифровка процессов компании / проекта. Особенности рабочего стола в Notion в проектах с большим количеством процессов | Веб-студия Nat.od.ua
Оцифровка процессов компании / проекта. Особенности рабочего стола в Notion в проектах с большим количеством процессов
Рабочий стол сотрудника называется рабочим потому, что это одна из главных точек входа сотрудника в вовлеченным им процессы. Чем больше процессов оцифровываются в компании, тем большее число баз данных существует в системе управления.
В компаниях с высокой степенью оцифровки деятельности, чаще всего встречаются следующие процессы в рамках которых фиксируются данные в базах данных Notion:
-
Команда (кто участвует в процессах компании)
-
Проекты (над чем работает команда)
-
Продукты (что создает команда)
-
Задачи (дефрагментация прогресса в результатах действий команды, который нужно достичь)
-
События (любые события, включая даты наступления ключевых показателей)
-
OKR / Цели (результаты деятельности команды спроецированные во времени)
-
Продажи (что и сколько продает команда)
-
Клиенты (кому продает команда)
-
Партнеры (кто участвует в деятельности проекта / компании)
-
Документы (нормативная, правовая, проектная и организационная база компании)
-
Wiki (база всесторонних знаний команды)
-
Отчеты (результаты достижений ключевых показателей процесса за период времени)
-
Совещания — на основе базы событий (встречи команды, на которых рассматриваются процессы, разбираются препятствия, задаются вопросы, ставятся дополнительные задачи и цели, принимаются решения)
Отдельно можно отметить группу состоящую из:
-
Inbox (входящая неотсортированная информация)
-
Вопросы (контекст, требующий разъяснения кем-то из членов команды)
-
Идеи / Предложения (инициативы, которыми делится команда)
-
Решения (согласие команды с действием определенной нормы)
-
Стоперы / Проблемы (все что препятствует прогрессу)
-
Письма (информация в виде документов, адресованная лично)
Давайте зададимся вопросом, для чего именно оцифровываются процессы компании. Явно не для бюрократии или, чтобы занять PM дополнительной рутиной. Прежде всего, это делается для:
-
определения реального статуса процессов в настоящем времени
-
выявления скрытых процессов и ответственных за них
-
привлечения внимания к процессу, с целью достижения желаемого результата
В отсутствие такого подхода команда сваливается в элементарный хаос, в котором реальный процесс затоплен факторами неизвестности, а руководители среднего звена получают выговоры за недостижение намеченных результатов или провала сроков.
Что дает оцифровка процессов?
-
ясность реального положения дел и текущего статуса процесса
-
возможность более точного прогнозирования событий
-
возможность оперативного реагирования с учетом статуса процесса
-
возможность создавать подробные отчеты по ключевым процессам деятельности
-
возможность проводить статистический анализ эффективности сотрудников
Большое число процессов, с которыми взаимодействует сотрудник должно иметь удобную архитектуру в рамках системы управления. Речь прежде всего о том, чтобы сотрудник имел возможность быстро получать информацию, к которой он имеет отношение.
В системах управления на базе Notion для этой цели создаются рабочие столы сотрудников, дешборды разделов и отделов. Ниже приведены примеры рабочих столов компаний разной деятельности.
Пример рабочего стола IT компанииРабочий стол интернет магазинаРабочий стол в маркетинговом агентствеСтроительная компания (мобильный интерфейс)
На примере рабочего стола IT компании разберем структуру и назначение его информационных блоков.
Сверху главное сквозное меню, позволяет осуществить переход в нужный раздел.
Навигационный блок удобен для моментального перехода к нужному процессу сотрудника минуя скроллинг по длинной странице рабочего стола. При этом фишкой данного блока является то, что включенные в название процессов ссылки ведут на базы данных, отфильтрованные именно на процессы конкретного сотрудника.
Делается это в рамках настройки шаблона рабочего стола один раз и далее ссылки генерируются автоматически для каждого сотрудника, применяющего шаблон к собственной карточке в базе команды.
Блок создания предстоящих событий
Данный блок нужен для создания митингов. Слева создаются предстоящие события, а блок справа удобен для назначения событий на ближайшие часы.
В середине страницы находятся блоки, включающие процессы с которыми пользователь взаимодействует не так часто.
Так слева мы видим предстоящие и прошедшие события (скрыты отдельным view базы), а ниже группу view базы спринтов (все, 🟢 – текущий и предстоящий). Справа как раз процессы с наименьшей частотой контактов, поэтому все они внутри toggle списков.
“Информационная доска” также скрыта в toggle список и включает группировку процессов, относящихся к оперативной информации: (вопросы, предложения / идеи), а также решения и стоперы (проблемы).
Все процессы имеют общие признаки состояний, таких как:
⌛ – ожидание
✔ – наличие ответа
⚡ – в процессе
👌🏻 – (вопрос решён, решение принято)
👍🏻👎🏻 – принятые или отклоненные идеи
⛔ – наличие нерешенной проблемы
В некоторых системах, где практикуется внутренний документооборот включающий: письма, приказы, распоряжения и требования создается дополнительный блок “сообщений”, в котором наличие новых сообщений для сотрудника отмечаются соответствующей индикацией. Когда сотрудник знакомится с документом любого из данных типов индикация пропадает. Цель индикации привлечь внимание сотрудника к ознакомлению с документом.
Подобные приемы индикаций также часто создаются непосредственно в карточках членов команды, цель которых сообщать о новых процессах, а также тех, которые еще не завершены.
Непонятными, используемые эмодзи выглядят только на первый взгляд. К подобным индикациям команда привыкает очень быстро.
✅ – число незакрытых задач
❓ – число вопросов, на которые нет еще ответа
❗ – число проблем, на которые нет реакции
💡 – Предложения, с которыми еще не ознакомились
📃 – Число писем, на которые нет реакции
⏰ – Число предстоящих событий, которые не подтверждены
еще пример индикации процессов в карточке члена команды
Здесь отражаются:
-
даты спринта
-
🔳 число задач
-
🟡 число возможных балов
-
❓ наличие/отсутствие незакрытых вопросов
-
✅ число закрытых задач
-
🟡 число полученных балов
Вернемся на рабочий стол, который рассматривается в данной статье как пример. Под блоком информации находится главный и самый структурированный блок — задачи.
Под названием блока находится локальное меню, позволяющее быстро увидеть задачи определенных типов, состояний и времени.
🟢 – задачи на сегодня
🔵 – эпики
⚡ – задачи текущего спринта
✅ – завершенные задачи
⚠ – просроченные задачи
⌛ – беклог (задачи оставленные на потом)
Далее
-
“все задачи” – содержит таблицу всех задач сотрудника в разных статусах
-
⚡ спринты — показывает все спринты сотрудника
-
доска — содержит все задачи сотрудника в формате board
-
♻ повторяющиеся — содержит шаблон, создающий список повторяющихся задач (еженедельные / ежемесячные), которые далее переносятся в базу задач
Отдельно стоит блок задач на сегодня, в котором задачи находятся на поверхности и не спрятаны в структуру раскрываемой папки. В нем также, все задачи разбиты на view задач относящихся к сегодня, но имеющих разный статус и тип.
Ниже находится группа папок, сортирующая задачи по большим группам:
🟢⚡ – текущий спринт
◀⚡ – прошлый спринт
⚠ – просроченные, 🔵 эпики и ⌛ беклог
Для кого-то может показаться это ужасным UX из-за количества папок и view баз данных. Но, на практике, к подобной структуре привыкаешь очень быстро, а экономия времени для доступа к нужному статусу или типу процесса оправдывает столь массивную архитектуру блока персональных задач.
Даже для пользователей Notion данная структура может показаться избыточной, но это скорее не от того, что она не практична, а в силу отсутствия опыта работы с подобными рабочими столами. Не в каждой организации, использующей Notion есть тот, кто в состоянии организовать рабочий процесс таким образом.
Сделать такой рабочий стол достаточно сложно, учитывая число предварительных настроек и множество включенных в него процессов. Для этого требуется опыт и немало знаний.
Если говорить об использовании Notion, как системы управления проектом при наличии специалиста можно создать шаблон процесса практически любой функциональности. Ниже приведен пример одного из лучших шаблонов, применяемых во время проведения командных встреч.
Здесь важно, чтобы весь обсуждаемый контекст не просто записывался в документ в виде стенограммы, но и приобретал статус процесса, в который вовлекаются нужные компетенции.
С таким подходом результативность проведения митинга повышается многократно, так как все ключевые мысли записаны и на их основе создаются:
-
новые задачи
-
ставятся вопросы, требующие получение дальнейших ответов
-
выносятся решения
-
выдвигаются инициативы
-
и т.п.
Умение раскладывать контекст на процессы, значительно повышает эффективность работы команды, так как ничего из обсуждаемого не остается упущенным и тем более забытым.
В крутых системах управления в Notion отдельное место имеет база знаний, фрагмент которой представлен и на рабочем столе, обсуждаемом в данной статье. Это wiki, создаваемое командой, записи которой относятся во всему, что требует пояснений.
Многое из того, что создается командой, требует отдельной справки, для этого и существует wiki проекта. На рабочем столе сотрудник видит справки, создаваемые самостоятельно, или с которыми он должен быть ознакомлен.
Пример базы знаний проекта
Совсем крутые базы знаний, как правило, представляют собой систему записей и связей типа Zettelkasten. Особенностью такой системы является не просто база знаний, а наличие связей между записями, которые погружают сотрудника в информационный процесс, создавая перед ним массив связанных друг с другом записей.
Как выглядит крутой zettel в Notion можно посмотреть в моем обзоре на Youtube.
А теперь, было бы интересно узнать у Вас, является приоритетной задачей в вашей организации / проекте оцифровка процессов помимо задач, продаж и прочих очевидных, без которых в принципе не возможен проджект менеджмент.
Фронтенд на Go с использованием библиотеки RUI / Хабр | Веб-студия Nat.od.ua
Фронтенд на Go с использованием библиотеки RUI / Хабр
Изначально библиотека RUI разработана для создания клиент-серверных веб приложений на языке go, где вся обработка осуществляется на сервере, а браузер используется только как тонкий клиент.
Однако в последней версии библиотеки (0.10.0) была добавлена поддержка технологии WebAssembly. Теперь стало возможным объединить серверную и клиентскую часть в единый модуль исполняемый в браузере. При этом требуются минимальные изменения в уже существующем проекте использующем библиотеку RUI
В этой статье я покажу как переделать уже существующий проект чтобы его можно было скомпилировать в wasm модуль и запустить его в браузере
Рассматривать данный процесс будем на примере демонстрационного приложения библиотеки RUI.
Для того чтобы подготовить проект в него необходимо внести следующие изменения:
-
добавить страницу загрузки приложения;
-
вынести из ресурсов приложения все мультимедиа файлы (графику, видео, аудио);
-
где необходимо, добавить в ImageView свойство “srcset”.
Страница загрузки приложения
Страница загрузки приложения уже добавлена в проект (файл “wasm_exec.html”) и выглядит она следующим образом
Это стандартная методика загрузки wasm модуля. Такой код вы можете увидеть практически в любом проекте на go для WebAssembly. Просто копируйте эту страницу в ваш проект
Код страницы очень простой: он загружает файл “demo.wasm” и запускает его.
Однако возникает вопрос: что за файл “https://habr.com/ru/post/698818/wasm_exec.js” и где его взять?
Файл “https://habr.com/ru/post/698818/wasm_exec.js” это файл из стандартной библиотеки golang. Он используется для согласования типов данных go и WebAssembly. Найти его можно по адресу “$GOROOT/misc/wasm/wasm_exec.js”.
ВНИМАНИЕ. Файл “https://habr.com/ru/post/698818/wasm_exec.js” может изменяться. Поэтому если вы переходите на новую версию go, то необходимо обновить и “https://habr.com/ru/post/698818/wasm_exec.js” на вашем веб сервере. Если этого не сделать то wasm модуль может перестать загружаться
Вынесение из ресурсов приложения всех мультимедиа файлов
Приложение скомпилированное в wasm модуль, по умолчанию, не умеет загружать картинки, видео и аудио из ресурсов приложения. Поэтому их необходимо исключить из модуля и разместить на сервере.
В принципе, данные файлы можно было бы оставить в ресурсах и подключать, например, так
imageView.Set(rui.Source, “data:image/png;base64,”+base64.StdEncoding.EncodeToString(data))
Однако этот способ вызывает жуткие тормоза в Safari и не рекомендуется к использованию (при этом в хроме и мозилле все работает быстро, никаких задержек нет).
Кроме того включение мультимедиа в ресурсы значительно увеличивает размер и так не маленького модуля, что, в свою очередь, увеличивает время загрузки страницы (а это всегда плохо).
Для того чтобы исключить все мультимедиа файлы, в проекте они вынесены в отдельную папку “media” и их включение в ресурсы осуществляется только если целевая платформа не js/wasm. Для всех платформ за исключение js/wasm ресурсы объявляются в файле resources.go
//go:build !wasm
package main
import “embed”
//go:embed resources media
var resources embed.FS
А для платформы js/wasm ресурсы объявляются в файле resourcesWasm.go
//go:build wasm
package main
import “embed”
//go:embed resources
var resources embed.FSДобавление в ImageView свойства “srcset”
Библиотека RUI поддерживает возможность использования разных вариантов изображения для различных плотностей пикселей экрана. Для этого в ресурсы приложения включатся несколько версий изображения. Например в рассматриваемом проекте это cat.jpg и [email protected], sample.png, [email protected] и [email protected]. Приложение само анализирует какие версии картинки есть и использует нужную.
Однако в случае wasm модуля картинки расположены на внешнем сервере и приложение не знает какие версии изображения имеются. Поэтому для платформы wasm необходимо с помощью свойства “srcset” явно задавать список вариантов изображений. Например:
if runtime.GOOS == “js” {
imageView.Set(rui.SrcSet, “cat.jpg, [email protected]”)
}
В свойстве “srcset” вы должны перечислить через запятую все варианты изображения.
Это все изменения которые необходимо сделать в проекте для поддержки технологии WebAssembly
Компиляция и запуск
Теперь необходимо скомпилировать проект. Для этого переходим в папку проекта и выполняем команду
GOOS=js GOARCH=wasm go build -o demo.wasm
В результате у вас появится файл demo.wasm.
Теперь если вы попытаетесь открыть в браузере wasm_exec.html, то вы увидите пустую страницу, а в консоли браузера следующую ошибку
Access to fetch at ‘file://…/demo.wasm’ from origin ‘null’ has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, isolated-app, chrome-extension, chrome, https, chrome-untrusted.
Этот говорит нам о том, что нам нужен http сервер. Напишем его на go
package main
import (
“fmt”
“log”
“net/http”
“os”
)
var projectPath = “
func main() {
http.HandleFunc(“/”, server)
log.Fatal(http.ListenAndServe(“localhost:8080”, nil))
}
func server(w http.ResponseWriter, req *http.Request) {
switch req.Method {
case “GET”:
fmt.Print(req.URL.Path)
switch req.URL.Path {
case “/”, “/wasm_exec.html”:
http.ServeFile(w, req, projectPath+”/wasm_exec.html”)
case “/demo.wasm”, “/wasm_exec.js”:
http.ServeFile(w, req, projectPath+req.URL.Path)
default:
path := projectPath + “/media/images” + req.URL.Path
if _, err := os.Stat(path); err == nil {
http.ServeFile(w, req, path)
return
}
path = projectPath + “/media/raw” + req.URL.Path
http.ServeFile(w, req, path)
}
}
}
После запуска данного сервера и перехода в браузере по адресу “localhost:8080” вы должны увидеть демо приложение библиотеки RUI
И в конце об одной проблеме с которой вы можете столкнуться если в качестве сервера будете использовать nginx или Apache. Если зальете данное приложение на данные сервера и попробуете открыть, то с большой вероятностью вы увидите пустой экран, а в консоле браузера ошибку:
Uncaught (in promise) TypeError: Failed to execute ‘compile’ on ‘WebAssembly’: Incorrect response MIME type. Expected ‘application/wasm’
Для решения этой проблемы необходимо прописать в настройках сервера для файлов с расширением “wasm” mime-тип “application/wasm”
На этом все
28 расширений VS Code для разработки документации / Хабр | Веб-студия Nat.od.ua
28 расширений VS Code для разработки документации / Хабр
Плагины, без которых техническим писателям жить можно, но сложно. В подборке — линтеры, форматирование, работа с git, проектирование API, подготовка схем и милота для удобной разработки.
ЛинтерыMarkdownlint
Самый популярный линтер для разметки Markdown. Подсвечивает распространенные проблемы.
Как пользоваться: https://marketplace.visualstudio.com/items?itemName=DavidAnson.vscode-markdownlint
Markdown All in One
Поддержка разметки Markdown в Visual Studio Code. Форматирование таблиц, оглавление, рендеринг в HTML.
Как пользоваться: https://marketplace.visualstudio.com/items?itemName=yzhang.markdown-all-in-one
LTeX – LanguageTool grammar/spell checking
Проверка орфографии и стилистики английского и русского языка по правилам LanguageTool.
Как пользоваться: https://marketplace.visualstudio.com/items?itemName=valentjn.vscode-ltex
Code Spell Checker + Russian – Code Spell Checker
Проверка опечаток в английском и русском тексте и коде. Находит опечатки даже в названиях переменных в коде Можно использовать расширение совместно с LTeX.
Как пользоваться: https://marketplace.visualstudio.com/items?itemName=streetsidesoftware.code-spell-checker
Proselint
Расширение линтера англоязычной прозы Proselint. Создатели сервиса вдохновлялись Чаком Палаником, Марком Твеном, Джоржем Оруэллом и другими писателями.
Как пользоваться: https://marketplace.visualstudio.com/items?itemName=PatrykPeszko.vscode-proselint
Textlint
Расширение open source сервиса Textlint, написанного на JS.
Как пользоваться: https://marketplace.visualstudio.com/items?itemName=taichi.vscode-textlint
Vale
Семантический линтер с возможностью задавать свои правила, настройки и конфигурации проверок на то, что вам нужно.
Как пользоваться: https://marketplace.visualstudio.com/items?itemName=errata-ai.vale-server
Форматирование и форматыPrettier – Code formatter
Расширение помогает так хорошо отформатировать текст в Markdown, что на него не ругается линтер.
Как пользоваться: https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode
OpenAPI (Swagger) Editor
Расширение для редактирования, форматирования спецификации OpenAPI (Swagger) в YAML или JSON.
Как пользоваться: https://marketplace.visualstudio.com/items?itemName=42Crunch.vscode-openapi#review-details
MdTableEditor
Расширение исключительно для таблиц Markdown. Подсвечивает строки, столбцы и добавляет кнопки для операций с таблицами на командную панель.
Как пользоваться: https://marketplace.visualstudio.com/items?itemName=clover.md-table-editor
GitHub Markdown Preview
Предварительный просмотр файлов Markdown в формате и стилистике GitHub.
Как пользоваться: https://marketplace.visualstudio.com/items?itemName=bierner.github-markdown-preview
Markdown Checkboxes
Расширение добавляет поддержку флажков и списков задач с предварительным просмотром.
Как пользоваться: https://marketplace.visualstudio.com/items?itemName=bierner.markdown-checkbox
PlantUML
Расширенная поддержка PlantUML.
Как пользоваться: https://marketplace.visualstudio.com/items?itemName=jebbs.plantuml
Asciidoc
Расширение поддерживает предварительный просмотр в реальном времени, подсветку синтаксиса и cниппеты для формата AsciiDoc.
Как пользоваться: https://marketplace.visualstudio.com/items?itemName=asciidoctor.asciidoctor-vscode
reStructuredText Language
Расширение для полноценной работы с языком разметки reStructuredText.
Как пользоваться: https://marketplace.visualstudio.com/items?itemName=lextudio.restructuredtext
Работа с системой контроля версий GitLens
GitLens поддерживает операции с git и визуализирует всю историю кода — когда была изменена строка или блок кода, как код менялся. Можно проследить эволюцию кодовой базы.
Как пользоваться: https://marketplace.visualstudio.com/items?itemName=eamodio.gitlens
Git Graph
Визуализирует весь таймлайн с коммитами и ветками. Позволяет работать с git через интерфейс.
Как пользоваться: https://marketplace.visualstudio.com/items?itemName=mhutchie.git-graph
Git Project Manager
Расширение позволяет открывать новое окно с репозиторием git из окна VS Code и быстро переключаться между репозиториями.
Как пользоваться: https://marketplace.visualstudio.com/items?itemName=felipecaputo.git-project-manager
Удобство и милотаMarkdown Emoji
✨
🚀: https://marketplace.visualstudio.com/items?itemName=bierner.markdown-emoji
HTTP/s and relative link checker
Поиск битых ссылок в Markdown-тексте.
Как пользоваться: https://marketplace.visualstudio.com/items?itemName=blackmist.LinkCheckMD
Settings Sync
Синхронизирует настройки и конфигурации VSCode. Для синхронизации используется Github Gist.
https://marketplace.visualstudio.com/items?itemName=Shan.code-settings-sync
Расширение конвертирует файлы Markdown в файлы PDF, HTML, PNG, JPEG.
Как пользоваться: https://marketplace.visualstudio.com/items?itemName=yzane.markdown-pdf
Markdown Paste
Расширение делает скриншоты и сразу же ссылки на них в файлах Markdown.
Как пользоваться: https://marketplace.visualstudio.com/items?itemName=telesoho.vscode-markdown-paste-image
Word Count
Подсчет символов в документе.
Как пользоваться: https://marketplace.visualstudio.com/items?itemName=ms-vscode.wordcount
Auto Close Tag
Добавляет закрывающий тег.
Как пользоваться: https://marketplace.visualstudio.com/items?itemName=formulahendry.auto-close-tag
Rainbow bracket
Каждой паре всех видов скобок расширение дает свой цвет радуги. Красным цветом подсвечены незакрытые скобки.
Как пользоваться: https://marketplace.visualstudio.com/items?itemName=2gua.rainbow-brackets
Live Server
Локальный сервер разработки с функцией перезагрузки в реальном времени для статических и динамических страниц. Рендеринг по кнопке.
Как пользоваться: https://marketplace.visualstudio.com/items?itemName=ritwickdey.LiveServer
Material Theme Icons
Иконки к файлам и папкам.
Как пользоваться: https://marketplace.visualstudio.com/items?itemName=Equinusocio.vsc-material-theme-icons
прокачиваем навыки владения CSS / Хабр | Веб-студия Nat.od.ua
прокачиваем навыки владения CSS / Хабр
веб-разработчик в HTDev
Любые навыки прокачиваются опытным путём и упорным изучением – это факт, с которым сложно не согласиться. Изучение языков программирования и каскадных таблиц стилей не являются исключением – достичь высоких результатов в этом вопросе удастся только благодаря регулярной практике.
Владея знаниями по вёрстке, можно достичь поставленных целей и перейти на следующую ступень профессионализма. В этой статье я расскажу, какие материалы мы с коллегами используем в своей работе: уверен, эта информация будет полезна разработчикам на CSS.
На базовом уровне
Цель: Помнить все свойства в CSS. Достигается примерно за 300 часов
Что изучать?
В первую очередь, синтаксис. А дальше по порядку:
-
Блочная модель https://doka.guide/css/box-model/
-
Специфичность https://doka.guide/css/specificity/
-
Принцип каскада https://doka.guide/css/cascade/
-
Методологии именования классов
Доклад: https://www.youtube.com/watch?v=1VM-vEItVeA&ab_channel=moscowcss
Презентация https://wsd.events/2016/10/01/pres/css-methodologies.pdf -
Позиционирование https://fls.guru/cssposition.html
-
Псевдоэлементы https://doka.guide/css/pseudoelements/ и псевдоклассы https://doka.guide/css/pseudoclasses/
-
Единицы измерения css https://fls.guru/css-units.html
-
Фон https://fls.guru/cssbackground.html https://yoksel.github.io/css-patterns/
-
Способы выравнивания элементов https://www.internet-technologies.ru/articles/centrirovanie-v-css-polnoe-rukovodstvo.html
-
Сетки Flex.
Теория: https://tpverstak.ru/flex-cheatsheet/Практика: https://the-echoplex.net/flexyboxes/ -
Основы SVG https://svgontheweb.com/ru/#preparation https://svgontheweb.com/ru/#implementation
-
Transform https://fls.guru/transform.html https://yoksel.github.io/pages/transform-functions/
-
Шрифты https://html5book.ru/css-shrifty/ https://doka.guide/css/font-face/Подробно о шрифтах: https://github.com/urfu-2015/verstka-lectures/blob/master/text/text.mdВариативные шрифты: https://yoksel.github.io/opentype-variable-fonts/
-
Дефолтные стили браузера: reset, normalize. https://htmlacademy.ru/blog/html/short-13https://htmlacademy.ru/blog/html/about-normalize-css
-
Валидное написание кода – по стандартам Консорциума Всемирной паутины (W3C). Проверить можно с помощью валидатора.
-
Стиль кода, к примеру:https://codeguide.academy/html-css.html#css
Как практиковаться?
С помощью платформ, например:
Для тренировки и визуализации небольшого участка кода применяются редакторы кода:
Где брать недостающую информацию?
Информацию по свойствам берём через онлайн-справочники:
На профессиональном уровне
Цель: Повысить скорость работы и использовать тонкости CSS на практике. Достигается примерно за 1000 часов.
Что изучать?
-
Адаптивная вёрстка https://doka.guide/css/media/
Теоретические примеры: https://tpverstak.ru/adaptive-cheatsheet/ -
Вёрстка под PixelPerfect https://htmlacademy.ru/blog/html/pixel-perfect
-
Особенности отображения стилей в разных браузерах
-
Препроцессоры SASS, Less, Stylus и постпроцессор PostCSS
-
Сетки Grid.
Теория: https://tpverstak.ru/grid/
Практика: https://alialaa.github.io/css-grid-cheat-sheet/ -
Работа с легаси (к примеру, float)
-
Продвинутые селекторы https://doka.guide/css/child/
http://css.yoksel.ru/nth-child/ -
Продвинутые фишки CSS
Например, z-index https://developer.mozilla.org/ru/docs/Web/CSS/z-index -
CSS-функции
https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Functions
https://dev.to/balaevarif/css-gio -
Стилизация скролла https://only-to-top.ru/blog/coding/2020-01-31-stilizaciya-skrolla-css.html
https://doka.guide/css/scroll-behavior/
https://doka.guide/css/scroll-padding/ -
CSS-анимация https://fls.guru/cssanimation.html
https://animista.net/play/text -
Углублённое изучение SVG https://svgontheweb.com/ru/
https://yoksel.github.io/svg-decoration/ -
SVG-анимация https://svgontheweb.com/ru/#animating
-
Библиотеки CSS:
Tailwind
Bootstrap
Foundation
Как практиковаться?
Самый эффективный способ – работая с макетами. Макеты можно найти в телеграм-каналах:
Или на платформах:
Где брать недостающую информацию?
В онлайн-справочниках:
https://doka.guide/css/
https://developer.mozilla.org/ru/docs/Web/CSS
В книгах:
-
Кит Грант «CSS для профи»
-
Дэвид Макфарланд «Большая книга по CSS»
-
Грег Сидельников «Наглядный CSS»
-
Леа Веру «Секреты CSS. Идеальные решения ежедневных задач»
На экспертном уровне
Цель: полная экспертность в вопросе и стремление развить свои навыки до высочайшего уровня. Достигается постоянным изучением CSS и практикой, измерение в часах невозможно.
Что изучать?
Фундаментальные механизмы CSS: обработка значений (value processing), каскад и наследование.
Оригинальная документация W3C https://www.w3.org/Style/CSS/Overview.en.html
Что практиковать?
Всё, включая апробацию новых фишек.
Где брать недостающую информацию?
Чтобы быть в курсе последних новостей:
-
Отслеживайте выход новых фишек в обновлениях браузеров
-
Читайте специализированные ресурсы, например, CSS-live
В заключении
Для человека, который только начинает изучать программирование, путь от первого знакомства с основами вёрстки до создания «одностраничника» без адаптивной версии займёт в среднем 70 часов. Однако работа верстальщика может включать не только создание лендингов, но и работу над масштабными проектами, такими, как, например, корпоративные порталы для федеральных компаний. Удержать в голове огромное количество знаний об особенностях CSS – очень сложно, плюс, из-за регулярного обновления версий браузеров добавляются новые свойства, функции, дорабатываются уже имеющиеся данные и появляются свежие подходы к вёрстке. Именно поэтому специалист, хорошо владеющий базой, всегда сможет найти для себя новые интересные грани в этой сфере и перспективы для развития своего профессионального потенциала.
Следим и вычисляем с Vue 3, или Как использовать watchEffect / Хабр | Веб-студия Nat.od.ua
Следим и вычисляем с Vue 3, или Как использовать watchEffect / Хабр
Привет! Меня зовут Алексей, я frontend-специалист SimbirSoft. В этой статье разберем новый метод слежения за реактивными свойствами watchEffect.
С появлением Vue 3 c Composition API стало доступно два метода слежения — watch и watchEffect. Если «старый» метод watch всем хорошо знаком и не должен вызывать затруднений у Vue-разработчиков, то новый метод стоит изучить подробнее. Материал будет полезен разработчикам, переходящим с Vue 2 на Vue 3 и всем «вьюшникам», которые еще не разобрались с этим методом.
Composition API предоставляет нам два разных метода слежения за реактивными свойствами — watch и watchEffect. Они похожи, но все же каждый полезен в определенных случаях. Рассмотрим, какие сходства и различия существуют у этих методов:
Общее
Отличия
● следят за изменениями зависимостей
● выполняют побочные эффекты в отдельной функции коллбэка
● предоставляют способ остановки слежения
● watch (без immediate) может использоваться для ленивого запуска побочных эффектов (watchEffect всегда отрабатывает немедленно после монтажа компонента)
● watchEffect автоматически следит за изменениями любых состояний (может быть несколько переменных для отслеживания)
● watch обеспечивает доступ к текущим и предыдущим значениям
Это были основные отличия, о других мы расскажем ниже.
Слежение за объектами и массивами в watchEffect
WatchEffect может отслеживать только адрес памяти реактивного объекта. Изменение элементов массива или свойств объекта не изменит адрес памяти и, следовательно, не вызовет срабатывания метода watchEffect:
При нажатии на кнопку add видим, что данные в массив добавляются, но watchEffect отрабатывает только один раз. WatchEffect всегда срабатывает только один раз после монтажа компонента, в watch нам приходилось указывать для этого immediate — true:
Нам нужно преобразовать реактивный объект обратно в массив с помощью spread-оператора:
{{ target }}
Теперь наш watchEffect успешно отрабатывает:
Для слежения за объектами будем использовать toRefs():
{{ data }}
Вызов функции stop() остановит действие watchEffect:
Параметры watchEffect
Метод watchEffect принимает два аргумента. Первый — это коллбэк-функция. Второй — объект конфигурации:
watchEffect(
() => {},
{
flush: ‘post’,
onTrack(e) {
debugger
},
onTrigger(e) {
debugger
}
})
Свойство flush определяет, запускается ли метод watchEffect до, после или во время повторного рендеринга страницы:
flush: ‘pre’ | ‘post’ | ‘sync’
По умолчанию созданные пользователем коллбек-функции наблюдателя вызываются до обновления компонентов Vue. Это означает, что если вы попытаетесь получить доступ к DOM внутри коллбек-функции наблюдателя, DOM будет в состоянии до того, как Vue применит какие-либо обновления.
Дополнительный объект настроек с опцией flush (значение по умолчанию — ‘pre’):
let stop = watchEffect(callback, {
flush: ‘pre’
})
Опция flush также может принимать значение ‘sync’, которое принудительно заставит эффект всегда срабатывать синхронно. Однако такое поведение неэффективно и должно использоваться только в крайних случаях:
watchEffect(callback, {
flush: ‘sync’
})
Если вы хотите получить доступ к DOM в коллбек-функции наблюдателя после того, как Vue его обновил его, вам нужно указать flush: ‘post’:
watchEffect(callback, {
flush: ‘post’
})Отладка watchEffect
Можно использовать опции onTrack и onTrigger для отладки поведения наблюдателя:
-
onTrack вызывается, когда реактивное свойство или ссылка начинает отслеживаться как зависимость;
-
onTrigger вызывается, когда коллбэк наблюдателя вызван изменением зависимости.
Оба коллбэка получают событие отладчика с информацией о зависимости, о которой идет речь. Обратите внимание, опции onTrack и onTrigger работают только в режиме разработки.
Аннулирование побочных эффектов
Иногда в функции наблюдателя могут быть асинхронные побочные эффекты, которые требуют дополнительных действий при их аннулировании (то есть в случаях, когда состояние изменилось до того, как эффекты завершились). Для таких случаев функция эффекта принимает функцию onInvalidate. Она будет использоваться для аннулирования выполненного и вызываться в следующих случаях:
-
когда эффект будет вскоре запущен повторно;
-
когда наблюдатель остановлен (то есть когда компонент размонтирован, если watchEffect используется внутри setup() или хука жизненного цикла).
{{ data }}
Снова запустим наше приложение:
Видим, что сначала отработала основная коллбек-функция, и в консоли вывелось basic function.
Если мы нажмем на кнопку stop, то сработает функция onInvalidate:
Если нажать на кнопку change title, то вначале выполнится функция onInvalidate, а затем основная функция. При изменении свойств onInvalidate будет всегда срабатывать первой:
Практическое применение watchEffect
Мы будем отменять запросы axios, если входные данные изменились, и старые данные больше не актуальны:
Функция setType изменит значение переменной type в зависимости от параметра, который был принят. WatchEffect следит за изменением переменной type, и при ее изменении делает запрос на получение постов или альбомов. Заметьте, мы нигде изначально не инициализируем запрос, поскольку watchEffect срабатывает один раз сразу при загрузке страницы:
Установим скорость сети в Slow 3G. И будем быстро переключаться по кнопкам load post и load alboms. Мы увидим, что запросы, которые больше не актуальны, отменяются.
Резюме
Мы разобрались с методом наблюдения за реактивными сущностями с помощью watchEffect.
Что следует запомнить о методе watchEffect:
-
он всегда срабатывает один раз после монтажа компонента;
-
он может отслеживать несколько переменных;
-
если вы хотите отслеживать изменения после обновления компонента, используйте опцию flush: ‘post’;
-
функция onInvalidate всегда срабатывает перед основной функцией;
-
для слежения за массивами используйте спред-оператор, а для слежения за объектами — функцию toRefs().
Подписывайся на наши соцсети! Авторские материалы для frontend-разработчиков мы также публикуем в ВК и Telegram.