Пишу про разработку вообще и в частности про: JavaScript, HTML5, CSS3, AngularJS, ReactJS, Agile.

Мой стартовый проект для разработки на реакте

Я достаточно давно поддерживаю репозиторий с базовым кодом для запуска проекта на реакте – react-webpack-starter. Сам пользуюсь им постоянно и, буду рад, если вы посмотрите и поделитесь своими соображениями. Вообще, я всем рекомендую держать под рукой такой инструмент для экспериментов. Тем более, что если это ваш основной фреймворк, то скорее всего вам ни раз придется на нем запускать проекты.

Итак, first things first, из чего состоит проект. То что основной фреймворк это React уже понятно, помимо него я так же добавил redux и sagas. Redux для управлениями моделью данных, Sagas – дополнительный уровень логики для управления асинхронными операциями. Это тот стек технологий, который я использую в каждом проекте.

Почти любое приложение работает с раутингом – как-то же надо разделить логику на разные страницы. Я взял стандартный раутинг, с которым работает большинство приложений написанных на этом фреймворке. Однако, мне не нравится функционал раутинга в его последней версии (4-ой), есть достаточно много ограничений, которые перевешивают плюсы новой версии.

Что нравится в 3-ей версии:

  • Все рауты объявляются в одном месте (гораздо проще этим управлять).
  • Может быть передан объектом.
  • Хорошо интегрируется с ридаксом, можно реагировать на изменения в адресе.

Что не нравится в 4-ей версии:

  • Каждый уровень раутинга расположен в отдельном родительском компоненте.
  • Может быть объявлен, только через компоненты.
  • Интеграция с ридаксом в альфа версии.

Структура файлов – это не последнее дело в разработке. Бардак в папках никому еще не добавил продуктивности. Итак, это мой вариант порядка:

Теперь по порядку о том что в папках

  • __mocks__ – это мок-файлы для тестов.
  • build – тут хранятся собранные файлы, готовые к заливке на сервер.
  • hooks – хуки для гита, например гнать проверку тестов и линтинга на каждом коммите.
  • jest – конфигурация тестов, поскольку проект на реакте, то использую jest.
  • source – исходные коды всех компонентов.
    • components – генерные компоненты, могут быть перенесены в другие проекты.
    • containers – контейнеры это компоненты, которые зависят напрямую от стейта ридакса. Тоже могут быть перенесены, но тогда нужно чтобы в ридаксе были схожие данные.
    • model – редюсеры, экшены, константы и саги. Все что нужно для ридакса.
    • styles – генерные стили, которые не получилось распределить по компонентам.
    • views – страницы приложения.
  • webpack – файлы конфигурации вебпака.
  • index.ejs – основная страница с html.
  • index.jsx – базовый файл приложения, с него начинается сборка.

Для тестов я использую jest, собственно, ничего более хорошего для тестов компонентов на реакте и нет. Вся конфигурация, как я уже упомянул находится в папке с одноименным названием. В самом репозитории не так уж и много тестов, только несколько, для того, чтобы “обозначить диспозицию”.

Для форматирования кода я использую eslint – самое популярное решение. Все базовые проверки построены на конфигурации от airbnb, с моими небольшими дополнениями.

Конфигурация webpack’а. Webpack у меня по-разному работает в среде разработки и, когда код собирается на прод. Это и логично, когда готовим файлы для прода, то нужно их и уменьшить и протестировать, а вот всем этим все время заниматься во время разработки не хочится. Поэтому и настройки будут отличаться. Вместе с тем все npm команды буду теже – npm run build соберет файлы как для прода так и для “девелопмента”, разница между двумя сборками будет только в значении глобальной переменной NODE_ENV

  • NODE_ENV=production npm run build – собирает для прода
  • npm run build – собирает для “девелопмента”

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

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

Поделиться:

Делаем качественный кастомный чекбокс

Многие примеры кастомных элементов совершенно не соответствуют проблемам действительности. Начнем с того как в принципе делается кастомный чекбокс и откуда идет необходимость. С необходимость все просто – нативный дизайн чебоксов мало кому нравится и смотрится не очень почти в любом сайте. Теперь как его, собственно, изменить – нативный компонент изменить не получится, каким он родился, таким и помрет, его можно только скрыть. После этого нам нужно как-то продолжить обрабатывать на нем события, для этого нам подойдет тег <label>, который будет передавать событие чекбокс-инпуту и менять его состояние. Таким образом можно сделать любой дизайн чекбокса только на базе стилей. Это только в общем приближении, теперь давайте обсудим как это сделать правильно с учетом разных ситуаций. А то в интернете понапишут всякого, потом не понятно как весь этот код править.

custom-checkbox

Для начала посмотрим на плохой пример такого чекбокса. Как ни странно, но он находится на сайте “стаковерфлов”: https://stackoverflow.com/a/34712423 Разберемся, что же не так на этом примере, понажимайте на чекбоксы и посмотрите какой будет результат:

See the Pen custom checkbox – bad css by Artem Demo (@artemdemo) on CodePen.

Разница между верхней и нижней группой только в размере шрифта. Как вы видите – нижние чебоксы вылезают за рамки и это выглядет ужасно. В чем дело? Проблем в позиции рамки чекбокса и “галочки” они не зависят друг от друга и поэтому съезжают.

А теперь давайте смотреть как лучше всего сделать чекбокс. Во-первых, для простоты перенесем input во внутрь тега label:

При таком подходе нам не нужно будет использовать id и for для того чтобы связать input и label . Далее, для того чтобы отображать галочку нам понадобится дополнительные тег, не стоит для этого использовать оба псеводкласса ::before и ::after. В общем виде это выглядит вот так:

Собственно все необходимые элементы у нас теперь есть, пора переходить к коду.

Для начала нам нужно скрыть сам инпут, потому что ему навесить новый стиль не получится. Ставим позицию в абсолют, что бы не сдвигал текст, видимость устанавливаем в hidden, потому что нам нужен его функционал, но он не должен быть видим пользователю:

Теперь описываем стиль рамки чекбокса. Использовать будем единицы “em”, это относительные единицы шрифта. Таким образом размер чекбокса будет меняться в зависимости от размера шрифта.

Основная работа закончена, теперь осталось обработать состояние “checked” инпута, так что бы чекбокс отображал галочку и все. Полный код примера находится ниже:

See the Pen checkbox by Artem Demo (@artemdemo) on CodePen.

Поделиться:

Как пропнуть ререндер компонента в реакте

Реакт сам решает когда рендерить компоненты. Это все хорошо, пока не появляется компонент, который по тем или иным причинам зависит от неких внешних данных и реакт не в курсе, что эти данные изменились.

Например, это может быть таблица, колонки которой задаются массивом объектов:

Каждый из объектов массива задает название колонки и то как будет выводится контент. Если контент будет выводится при помощи более сложной функции, которая по замыканию использует сторонние данные, то вот тут будет проблема. Ваша таблица не будет отрендерина, если данные по замыканию изменятся. Это связанно с тем, что реакт не отслеживает все изменения на свете, а только те, что в стейте (стейт компонента, либо сейт приложения).

В описанном случае, есть два варианта решения. Первое (и скорее всего самое правильное), это подумать над исполнением. Очень может быть что вы просто не так уж хорошо написали код и вполне возможно, что стоит снова подумать над архитектурой. Второй вариант – это использовать атрибут “key” реакта.

Наверняка, вы все уже не раз добавляли этот атрибут элементам массива при рендере. А не думали зачем это надо? Дело в том, что реакту нужен этот атрибут для двух целей:

  • отличить элементы в массиве
  • определить изменился компонент или нет

Стоит обратить внимание на то, что нигде в документации не написано, что “key” должен использоваться обязательно в массиве. Вы можете добавить его любому элеменут и в тот момент, как он изменится, реакт заново отрендерит компонент.

Поделиться:

Плагин для борьбы с CORS ошибками в хроме

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

Ведь в чем проблема CORS ошибок – либо браузер блокирует запрос из-за того, что сервер возвращает не соответствующий хедер “Access-Control-Allow-Origin”. Либо сам сервер блокирует запрос потому что его не устраивает то, что пришло в хедерех “Referer” или “Origin”. В обоих случаях все упирается в то, что послал браузер, а значит может быть переделано.

Для того, чтобы с эти справиться ставим плагин requestly.

requestly-home-page

requestly-modify-headers

Скорее всего вам потребуется добавить 3 правила.

Два первых правила предназначены для изменения двух хедеров в Request:

  • Referer
  • Origin

У обоих в значении должен быть домен, до которого нужно достучаться.

В третьем правиле нужно модифицировать хедер в Response, который называется “Access-Control-Allow-Origin”. Устанавливаем его в значение “*” (звездочка без кавычек).

Имеет смысл добавить условие, по которому эти правила будут применяться. Например, урл адрес должен содержать определенный домен. Вот и все, никаких больше ошибок не будет.

Поделиться:

Toast UI – набор компонентов для интерфейсов

Коротенечко, тезисно о найденной библиотеки. Ребята из китайской компании toast.com постоянно пилят UI компоненты для интерфейсов. Мне пока не удалось воспользоваться ни одним из них (не было необходимости), но суля по количеству “звездочек” на гитхабе народ ценит и любит их решения.

Итак что, у нас есть:

Графики

Набор графиков. Все написано своими руками, не зависит от сторонних библиотек.

toast-ui-charts

Календарь

Вот это необычно, мне не приходилось сталкиваться с опенсорсными календарями. Это еще и выглядит очень прилично.

toast-ui-calendar

Редактор

HTML редактор – достаточно распространенный компонент. Где я только такие не встречал.

toast-ui-editor

Таблицу для вывода данных

Интересное решение. Таке ощущение, что таблица выводит все данные одним махом, без постраничного вывода. Это может быстро работать, если правильно подойти к решению.

toast-ui-grid

Поделиться:

Пишем модульный код для контентного сайта

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

conditioner

Собственно, не все сайт должны быть одностраничными. Особенно если речь идет об индексации и времени рендера для конечного пользователя. Ничто так быстро не рендерится в браузере как обычный html, а уж если нужно поддерживать разные устройства с разным объемом памяти, то вот тут и начинаются танцы с бубном.

Так вот в случае с контентым сайтом “js сахар” добавляется модульно, там где нужна интерактивность:

  • Поиск с автозаполнением
  • Форми с проверкой валидности полей
  • Выпадающий список с поиском
  • и так далее

Таких модулей может быть несколько на странице, а может и вообще не быть, все зависит от контента. Сайт же у нас контентный, вот от него и пляшем. При таком подходе хочется, чтобы необходимый js загружался только когда он нужен, а не одним модулем на каждой страницу. Вот тут и возникаем проблема. Как это обеспечить?

Один файл со всем кодом писать не хочется – ибо он со временем разрастется и станет бегемотом. Как-то исхитриться и компоновать код под каждую страницу? А как это автоматизировать? Очень не хочется вести список модулей для каждой страницы и не забывать его постоянно обновлять. Нужно решение, которое бы позволяло подтягивать модули в зависимости от html, то есть весь необходимый функционал был бы описан в разметке страницы, а внешний модуль подтягивал бы релевантный код.

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

Страницу долго придумывать не будем, просто возьмем прием работы бустрапа – Pricing example. Я просто взял весь внутренний код и начал работать с ним

content-js-site

Добавим немного интерактивности, пусть при наведении мышкой на карточку с ценой она увеличивается. Все исключительно на js, что бы показать работу. Для анимации будем использовать библиотеку animejs – достаточно простой вариант анимации не на базе css.

Теперь сама кодовая база. Основной файл, через который webpack будет компилировать все остальные будет index.js. В этом файле описываем как вебпаку нужно будет загружать модули – moduleImport. Это стандартный мета-синткас менеджера сборки.

Теперь сам модуль для анимации карточки – modules/priceCart.js

Теперь добавляем код модуля в сам html:

Вот, собственно, и все. Можно продолжать экспериментировать 🙂 Кстати, полный код находится вот здесь: https://github.com/artemdemo/content-js-site

Ссылки по теме:

Поделиться:

Используем nvm для работы с node.js

Часто, работая над несколькими проектами, требуется использовать несколько версий node. Да даже если не работаешь над несколькими очень хочется самому управлять тем какая версия ноды стоит на компьютере. Потому что не все библиотеки проекта успевают обновиться под обновленный API.

Отдельно хочется сказать про мак. Потому что на маке все хочется устанавливать через brew, в этом нет никаких проблем пока они не начинаются 🙂 – особенно, когда вдруг “апнулась” версия ноды и весь проект перестал собираться. Поэтому имеет смысл использовать сторонний менеджер версий, например nvm.

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

Устанавливаем сам nvm:

Теперь добавляем скрипты для запуска nvm в профиль баша (~/.bash_profile, ~/.zshrc, ~/.profile, or ~/.bashrc):

Особенно внимательно проверяем профили оболочки (если таковая используется, например, ~/.zshrc). Там тоже должен быть прописан запуск nvm.

Ставим lts версию ноды:

Теперь указываем какая версия ноды должна запускаться по умолчанию, например стабильная (если установлена только lts, то будет выбрана она):

Все, теперь можно ставить несколько версий параллельно и переключаться между ними.

Ссылки по теме:

Поделиться:

Топ 10 js ошибок из 1000+ проектов

Для начала немного контекста. Rollbar – это облачное решение для аггрегации ошибок. У них есть библиотеки для интеграции практически с чем угодно, в том числе и с браузерным приложением.

Так вот эти ребята написали статью с обзором 10 самых распространенных js ошибок, которых их сервис поймал. Достаточно интересное чтиво. Вот топ лист, кстати:

top-js-error-msgs

Ребята конечно написали статью для того чтобы пропиарить свой сервис. Никаких к ним при этом претензий конечно быть не может. Все правильно делают. Вместе с тем и нам очень много пользы.

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

Например, когда сафари вабрасывает ошибку с сообщением “TypeError: ‘undefined’ is not an object”, то хром напишет “Uncaught TypeError: Cannot read property bar of undefined”. Хотя это будет один и тот же случай. Для иллюстрации посмотрим вот как эта ошибка выглядит в хроме:

cannot-read-property

И вот как она же выглядит в сафари:

safari-undefined-error-msg

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

Поделиться:

Приложение на js без фреймворков

Решил написать js приложение без использование фреймворков. Не хочу сказать, что это самый правильный путь, но имеет смысл попробовать писать и так, чтобы лучше понимать как работает язык, ну и что бы лучше понимать как отвечать на вопрос “А зачем нам, собственно, все эти фреймворки? Давайти так писать!”. Вовсе не хочу сказать, что без фреймворков – это путь джедая, или что мой подход к решению самый верный. Я экспериментирую с языком в свободное от работы и личной жизни время, чего и вам желаю 😉

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

Во-первых, роутинг. Приложение конечно будет SPA, так что без этого ни куда. Быстрый поиск поиск по интернету выдал несколько готовых решений, а наглый подсчет количества зваздочек в гитхабе и активность загрузок в npm помолги выбрать победителя, им стал page. Кстати, если вам нравится что-то другое, то отпишитесь в комментариях плиз, интересно кто, что использует.

Во-вторых, темплейтинг. Хотите сами манипулировать DOM’ом? Хардкор – это ваш путь, даже завидую. Я предпочитаю отдать бразды правления тут профессионалам. Давно хотел протестировать lit-html, видимо пришло время. Пользуетесь другим решением? Отлично, как и в прошлый раз – мне интересно услышать ваше мнение.

Идем дальше, нужно как-то хранить данные в памяти и эффективно передавать между компонентами. Мой выбор redux, все хотел заиспользовать его в не контекста реакта.

Над дизайном заморачиваться вообще не будем. Берем bootstrap последней версии и все.

Кстати, по поводу стилей, нужен препроцессор, иначе не дело это. Я решил взять postcss, пора немного отойти от less, а то он прямо везде.

Заметили, что jQuery нет? Это по-дизайну, отвык я от него, предпочитаю работать без этой библиотеки, и так полно библиотек подцепил.

Теперь как все это собирать будем. Разумеется webpack, как же иначе.

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

Структура

Разумеется приложение нужно разбить на составляющие и разнести логично по папочкам. Так что бы потом тем кто придет после нас можно было разобраться в том что тут происходит. В процессе проектирования было несколько итераций с разными подходами, не буду вас мучить всеми подробностями – расскажу просто о том к чему пришел:

Теперь отдельно о каждой папке:

  • components – тут хранятся основные компоненты. Компонентами, в контексте этого приложения, я называю программные единицы, которые базируется на API унаследованном от HTMLElement.
    • AppRoot – корневой элемент приложения, будет располагаться в index.html
    • Cart – компонент корзиный, будет отображать иконку и кол-во товаров в ней
    • MainMenu – меню
    • RouteLink – ссылка для роутинга
    • Router – корневой компонента роутинга, в нем будут рендерится все страницы
  • model – все, что касается “бойлерплейта” ридакса: actions, constants, reducers.
  • pages – раутинг отображает страницы. Они являются основными контейнерами, для остальных элементов. Плюс страницы завязаны на API раутинга, поэтому они выделены в отдельную папку.
  • routeControllers – контроллеры для раутинга. По факту, это инструментарий для обработки коллбеков раутенга.
  • services – вспомогательные сервисы, дополнительный функционал, который больше никуда не поместился
  • views – рендеры, функционал lit-html

Весь исходный код конечно есть в открытом доступе js-webpack-starter

Все, кто хочет посмотреть – велкам, если есть какие рацпредложение, то конечно я хочу их услышать. Особенно, если это в виде пулл-реквестов, а то воздух сотрясать я и сам умею 🙂

Поделиться:

Конвертируем картинки в pdf в линуксе

Мне периодически требуется конвертировать картинки в pdf. Думаю, что задача достаточно распространенная, поэтому хочу порекомендовать как это сделать в линуксе без особого напряжения вообще – одной строкой:

За что отвечает каждый из параметров думаю и так понятно.

jpg-pdf

Хочу только добавить еще один вариант команды, которым иногда пользуюсь:

В этом случае картинку ужмутся на 10% (да, в команде указанно 90%, я не ошибся) и в консоле будет писаться какая картинка обрабатывается.

PS

Стоит отметить, что convert имеет еще туеву хучу настроек под все что угодно, так что если есть делание поразбираться, то там непаханное поле

Ссылки по теме:

Поделиться: