react-redux-starter-kit icon indicating copy to clipboard operation
react-redux-starter-kit copied to clipboard

Css modules

Open NikitaRzm opened this issue 6 years ago • 25 comments

В свете последних событий по поводу cssinjs есть пропозал опционального перехода на css-modules - опционально - потому что не на всех размерах проектов есть смысл изолировать стили.

Предлагается юзать изолированные css-modules в связке с типизацией через https://github.com/olegstepura/typed-css-modules-loader.

Предлагаю тему на ресерч - сложность реализации, использования и профиты по сравнению с обычным глобальным css.

P.s. типизация css-module возникает только когда применяется сама изоляция через css-modules.

NikitaRzm avatar Jan 22 '19 06:01 NikitaRzm

может на вскод какое-нибудь расширение есть для генерации всего этого на лету? можно же в тсконфиге выставить флаг чтобы он не продалбывал типы при импорте json-файла. Может что-то подобное можно замутить с помощью расширения.

in19farkt avatar Jan 22 '19 06:01 in19farkt

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

NikitaRzm avatar Jan 22 '19 06:01 NikitaRzm

Меня на тему борьбы с глобальностью CSS-a всегда одна вещь смущала: глобальность CSS-а в какой-то степени нас заставляет для новой сущности каждый раз придумывать свое уникальное имя. Т.е. когда в системе есть несколько сущностей, а имя у них одно и то же, имхо, такого быть не должно в принципе, это будет лишний раз путаницу вводить. Ну типа неймспейс в рамках блока у нас уже есть, а в рамках всего проекта делать уникальные имена - не знаю, хорошая ли это идея, потому что иметь 2+ блока с одним именем - не очень как-то. Хотя интуитивно, конечно, может быть дискомфорт чисто от того, что все классы глобальные и риск коллизий есть, поэтому я сам не уверен во всем что написал на 100%.

chmnkh avatar Jan 22 '19 06:01 chmnkh

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

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

in19farkt avatar Jan 22 '19 06:01 in19farkt

tslint - это про кодстайл, он здесь совсем не при чем)

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

Меня интересует типизация и снижении ошибок при расстановке классов. Надо это решить, есть решение, но оно сайдэффектит css-модулями ))

NikitaRzm avatar Jan 22 '19 06:01 NikitaRzm

@chmnkh почти на всех проектах, на которых я работал такие коллизии случались)) Да это не часто бывает, но всё же бывает) Идеология бэма предполагает что каждый блок в плане стилей должен быть уникален и без css-модулей за этой уникальностью ты должен следить сам, а с ними ты можешь расслабиться и не думать об этом.

in19farkt avatar Jan 22 '19 06:01 in19farkt

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

NikitaRzm avatar Jan 22 '19 06:01 NikitaRzm

@NikitaRzm да, tslint - это про кодстайл, но его можно расширить плагином и пусть еще следит за наличием классов в стилях (хотя хз возможно ли это), я не говорю про автодополнения и прочее, пусть хотя бы предупредит что используемый класс не объявлен в стилях.

in19farkt avatar Jan 22 '19 06:01 in19farkt

за этой уникальностью ты должен следить сам, а с ними ты можешь расслабиться и не думать об этом.

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

Вообще говоря, я не сразу вот о чем подумал: если учесть что чувак на проекте не один и его код все таки другие люди смотрят, тогда мой аргумент в общем-то ни о чем)

chmnkh avatar Jan 22 '19 07:01 chmnkh

Я думал смысл юзать бэм отпадает, если юзаем css модули) вообще мне нравится тема, я погуглил, можно попробовать

clicktronix avatar Jan 24 '19 11:01 clicktronix

Ага, бэм полезен только как пример для некоторого подражания остаётся юзать, напрямую в проекте он больше не нужен

Znack avatar Jan 24 '19 15:01 Znack

ну можно было бы модификаторы бэмовские оставить, например, ибо они имхо прям хороши именование типа блок__элемент то уже смысла не имеет, и стили так опрятнее будут в принципе

chmnkh avatar Jan 25 '19 09:01 chmnkh

бэм помогает еще в целом структуру кода локальную организовать ведь ) читать легче и писать быстрее иногда )

NikitaRzm avatar Jan 26 '19 09:01 NikitaRzm

Вот еще один лоадер https://github.com/Jimdo/typings-for-css-modules-loader, но он походу заброшенный

in19farkt avatar Feb 25 '19 05:02 in19farkt

а вот eslint плагин, хз будет ли он работать с тайпскриптом, но если что можно адаптировать под ТС. https://github.com/atfzl/eslint-plugin-css-modules

Он еще и проверяет css на неиспользуемые классы

in19farkt avatar Feb 25 '19 05:02 in19farkt

попробую в кучу плюсы и минусы собрать навскидку плюсы:

  1. типизация
  2. бэм-цн можно будет на помойку выбросить в принципе то, что у нас в класснейм будут строки подставляться, а не какие-то мутные функции со свойствами, нас избавит от некоторых проблем, типа таких, что приходится в некоторых местах (например если мы в mui-компоненты свои классы суём и помощью бем-цн) в ручную вызывать toString на бем-цн "функции", т.е. вот так вот делать:
className={b('eto-dich').toString()}

в муи компонентах так приходится писать, потому что там под капотом юзается classnames, который не может переварить функцию b('eto-dich') и вываливает в класснейм всякую чушь. b('eto-dich')() тоже нельзя написать, потому что в типах для b('eto-dich') сигнатуры вызова нету и это как будто бы объект, и тайпскрипт нам по шапке бьет за попытку его вызова. Не исключено, что кроме муи это еще где-то может за одно место укусить. Не то чтобы это прямо критично, но не очень приятно. 3) коллизий стилей не будет 4) таки удобно в тестах, например, написать

component.find(`.${styles.abc}`)

а не лезти в компонент и не смотреть как там класс написан. Да и вообще таким образом классы будут из одного источника исходить.

минусы:

  1. если нам где-то нужно заселектить элемент четко по строке с классом - моментальный крах из-за уникальных классов (Серега рассказывал, что им это в аналитике на птичке мешало; Влад рассказывал, что тоже в тестах на селениуме тоже надо было селектить по классам, в итоге какими-то костылями разрулили)
  2. Сереге чото там конкатенировать неудобно было, хотя я в целом не понял проблемы, ибо можно classnames юзать и должно быть ок

я так понял в целом @Znack не супер ЗА цсс-модули, поэтому он мб прояснит чего

chmnkh avatar Mar 28 '19 10:03 chmnkh

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

Но хз можно ли добавить дополнительный атрибут в тип html-элементов, чтобы тайпскрипт на нас не орал.

in19farkt avatar Mar 28 '19 11:03 in19farkt

Это просто очень больно будет — на все элементы вешать отдельные атрибуты. Хотя это действительно практика получше, чем селекты по классу, так как с классами маркетологи жёстко завязываются на разработчиков, и вторые постоянно забывают про первых и меняют классы :)

Znack avatar Mar 28 '19 12:03 Znack

Ага, еще ништяк, когда ты смотришь в верстку, то видишь все ключевые элементы, и внося правки ты понимаешь что и где может отвалиться.

У нас вроде даже где-то в стандартах был такой пунктик (not SPA), что если мы по классу привязываем какие-то обработчики к элементам, то нужно добавлять класс с префиксом js-, и по нему делать такую привязку. Тут мне кажется очень похожая ситуация.

in19farkt avatar Mar 28 '19 15:03 in19farkt

Вот еще наткнулся на довольно крутой подход к написанию стилей

Тут доклад, немного теории по теме и небольшая презентация этого решения.

Основные плюсы на мой взгляд:

  • очень близко к нативному написанию стилей, за исключением некоторых деталей
  • изолированные стили
  • верстка получается очень чистой и семантичной
  • стимулирует использовать семантичные теги
  • есть динамические стили, не как в jss за счет потери производительности, а на основе css-переменных
  • бенчмарк в огнях :) Для наглядности, я форкнул оригинальный бенчмарк и добавил туда отрисовку с использованием нативного css.

Из минусов:

  • альфа версия, не большое комьюнити
  • пока хз че с ssr
  • есть рантайм, но он вроде как минимален

@chmnkh @Znack @clicktronix @NikitaRzm @kinda-neat что скажете?

in19farkt avatar Jun 25 '19 05:06 in19farkt

Это получается, стиль написания внутри  js - но экстрактится на этапе сборки в статику? Выглядит прикольно довольно таки конечно. Можно поресерчить - я так глянул в общем - вроде все что надо есть. Надо детально смотреть.

P.S. Когда заходишь на страницу технологии применения css - не ожидаешь что страница поедет этим самым css в последнем сафари :D

image

NikitaRzm avatar Jun 25 '19 05:06 NikitaRzm

Не обязательно в js, можно писать в css и даже пропустить его через PostCSS. Если нужны динамические стили от пропсов, то можно писать в стиле CSS-in-JS (и похоже не обязательно это делать в js файле, но это не точно).

Но в итоге, весь css код попадает в js бандл и также инжектится при старте приложения как в любой CSS-in-JS библиотеке.

in19farkt avatar Jun 25 '19 05:06 in19farkt

вот ишу у них нашел. Beta roadmap. Судя по ней всё готово к бете, осталось только документацию и экзамплы написать.

in19farkt avatar Jun 25 '19 06:06 in19farkt

Тогда можно подождать, пока они закончат - и садиться изучать и пробовать применить на демке если все ок

NikitaRzm avatar Jun 26 '19 04:06 NikitaRzm

@in19farkt про написание стилей все верно, можно писать стиле как эксклюзивно в отдельных css файлах как в стандартном подходе с css-modules, так и в js файлах как те же styled-components. Если подключен reshadow webpack loader то стили будут доставаться из js файлов во время сборки и не будут раздувать js бандлы и инлайниться в хэд при инициализации приложения.

Подход с написанием стилей в js файлов удобен только в двух случаях

  • разработчик уже привык к интерфейсу css-in-js решений
  • необходимость в runtime переменных

PS: спасибо за багу в сафари на стойте документации, в ближайшее время пофксим =)

antonk52 avatar Jul 01 '19 13:07 antonk52