[Прим. перев.]: предлагаю вашему вниманию перевод статьи Марка Отто, разработчика GitHub, бывшего разработчика Twitter, создателя самого известного CSS фреймворка Bootstrap. В этой статье он рассказывает о внутреннем устройстве CSS проектов GitHub.
Меня всегда интересовали подробности процесса разработки других продуктов, особенно их гайдлайны и подход к использованию CSS. Учитывая мою склонность к деталям чужого CSS кода, я решил написать о подходе к CSS в GitHub.
Как уже было упомянуто выше, мы используем SCSS. Этот выбор был сделан еще до того, как я стал принимать участие в разработке, но я с ним согласен (несмотря на то, что Bootstrap написан на LESS). Наш SCSS компилируется и подключается с помощью Rails asset pipeline и Sprockets (на данный момент). Подробнее будет описано ниже.
Как на счет LESS, или Stylus, или ...? Я не думаю, что GitHub когда-нибудь перейдет на LESS. Мы не хотели бы что-то менять в этом отношении, так как нет никаких очевидных преимуществ.
Почему препроцессор? Наш внутренний фреймворк включает в себя набор переменных (таких как шрифты и фирменные цвета) и примесей (в основном для префиксов), которые делают процесс написание кода быстрее и проще. В настоящий момент мы не используем Autoprefixer, но нам следовало бы сделать это. Так мы моглибы свести на нет все наши существующие примеси. Надеюсь, мы осуществим это в ближайшее время.
Мы также не используем source maps, но скоро это изменится. (Для тех, кто не знает, source maps позволяют увидеть в отладчике, к какому из исходных SCSS файлов относится конкретный набор стилей, в отличие от скомпилированных и минифицированных файлов. Они потрясающие.)
Мы используем инструменты SCSS довольно ограниченно. У нас есть переменные для определения цветов, примеси, функции для работы с цветом, математические функции и уровни вложенности. Нам не требуется перебирать классы, создавать глобальные настройки или что-то подобное. Мне нравится простота, которая у нас получилась.
Обычно архитектура CSS представляет из себя BEM или OOCSS. Мы склоняемся к OOCSS, но какого-то целостного подхода у нас нет. Наши основные правила это:
Еще несколько недель назад мы не использовали анализаторы кода. У нас было несколько общих соглашений, но каждый разработчик имел свой собственный стиль, и форматирование каждого из нас было несколько уникальным. На данный момент каждая сборка проходит процесс анализа SCSS кода и падает если:
В CSS описан класс, который не используется в шаблонах app/views/.
Один и тот же селектор используется несколько раз (так как они должны быть всегда скомбинированы).
Нарушены основные правила форматирования (предельная вложенность, разрывы строк между наборами правил и др.)
В целом, есть несколько правил, которые позволяют держать нашу кодовую базу достаточно опрятной. Они не учитывают расхождения в стиле комментирования или архитектуру, но это именно то, что нужно каждой команде. И каждый из нас может предложить и улучшить что-либо.
CSS проекта GitHub состоит из 2х файлов: github и github2. Данное разделение было добавлено несколько лет назад, для решения проблемы работы с IE, который ограничивает количество селекторов до 4,095 на 1 файл. Данное ограничение распространяется на IE 9 версии и ниже. Из-за того, что требованием GitHub является минимум IE9, нам приходится разделять файлы.
По состоянию на сегодняшний день, наши 2 файла состоят примерно из 7000 селекторов. Как это соотносится с другими сайтами?
Эти данные были собраны с помощью cssstats.com. Это небольшой инструмент, который смотрит на ваш CSS под таким углом, под которым большинство людей, включая меня, обычно этого не делают. Также у нас в GitHub есть графики, которые мы используем в собственных целях.
В GitHub CSS и JavaScript, подлючается с помощью Sprockets и require. Мы храним оба наших CSS пакета в отдельных директориях внутри app/assets/stylesheets. Вот так это выглядит:
Мы подключаем наши зависимости (Primer — это наш внутренний фреймворк) и затем загружаем все файлы из директории scss. Какой будет порядок подключения решает Sprockets (мне кажется, что алфавитный). Легкость, c которой мы можем подключать наши таблицы стилей (простым прописыванием require_directory) поражает. Но у этого подхода есть свои минусы.
Порядок применения стилей играет важную роль. Из-за использования Sprockets у нас иногда возникают специфические проблемы. Это происходит потому, что новые файлы могут быть добавлены в любой пакет в любое время. В зависимости от имени файла, новые стили могут появится в разных местах в скомпилированном CSS.
Кроме того, используя Sprocket, вы не имеете немедленного и автоматического доступа к глобальных переменных и примесям в ваших SCSS файлах. Это значит, что вам придется импортировать их явно в начале каждого файла, который ссылается на переменную или примесь.
У нас есть огромное количество графиков для мониторинга работы сайты и нашего API. В том числе мы отслеживаем некоторые инересные статистики по фронтенду. К примеру, размер двух наших CSS пакетов за последние 3 месяца:
Также мы отслеживаем количество селекторов на странице. Перед нами по-прежнему стоит задача уменьшить количество селекторов по тегу.
Так как мы регулярно обновляем наш CSS и делаем это множество раз каждый день, нам приходится постоянно сбрасывать кеширование наших довольно больших файлов. Пока что мы не сильно продвинулись в оптимизации размера этих файлов и ограничения сбрасывания кеша, но мы уже начали задумываться об этом более серьезно. Было бы неплохо иметь основной пакет, который изменяется редко, и второстепенный, често изменяемый.
Когда я работал в Twitter, у нас было 2 пакета (не уверен, что это все еще так), основной и дополнительный. В основном были описаны все стили, которые требовались, чтобы отобразить первый твит как можно быстрее. Все остальное хранилось в дополнительном. Учитывая любовь GitHub ко всему быстрому, это как раз то, что мы планируем рассмотреть в ближайшее время. В настоящее время разделение на файлы является случайным.
Как правило, мы не занимаемся производительностью селекторов. Мы знаем о плохих практиках — большая вложенность, использование селекторов по id и элементу и др., но мы не пытаемся через чур оптимиризовать это. Единственным исключением является страница «diff»'а. В связи с обширной разметкой, требуемой для отрисовки diff-a, мы избегаем селекторы атрибутов, такие как [class^=«octicon»]. Если использовать их слишком часто, такие селекторы по атрибутам могут положить браузер (и делали это).
Для любопытных, Jon Rohan, разработчик GitHub, делал отличный доклад о производительности CSS в GitHub, который раскрывает эти проблемы.
Говоря о документации, мы проделали отличную работу над ней, но все еще работаем над внесением улучшений в нее. Мы выложили в публичный доступ наш CSS гайд и все наши основные правила по написанию CSS. Также мы выложили примеры большинства наших компонентов. Она собрана с помощью KSS, генератора style-гайдов.
Наша документация не идеальна, но она помогает людям найти и использовать, то что они хотят. Кроме того, это отличный способ показать новобранцам то, как мы работаем, чтобы ускорить их вливание в процесс разработки (как это было со мной около 2-х лет назад).
Я ссылался на Primer ранее, но для тех, кто не знает поясню: Primer — это наш внутренний фреймворк, который содержит стили и компоненты, используемые как в публичных, так и в наших внутренних проектах. Он включает в себя:
Мы используем его на GitHub.com, Gist и нескольких внутренних приложениях. Как правило, если что-то может быть использовано в другом приложении, мы включаем это в Primer. Большинство компонентов Primer'а задокументированы в нашем гайде.
В наших проектах присутствует некоторое количество легаси кода, и CSS входит в него. В отличие от оперсорсных проектов со строгими правилами версионирования, мы часто забиваем на это. Мы принимаем решение об удалении части кода в двух случаях:
Сам процесс рефакторинга CSS в GitHub не является уникальным. Мы находим плохой код, удаляем его и выкатываем как можно быстрее. Удалить код может любой участник команды. К нашей команде присоединяется множество крутых разработчиков, но у нас есть и нерды, которые следят за тем, что можно удалить, а что нет.
Если у вас есть вопросы по этой статье, Bootstrap, GitHub или еще о чем то, спрашивайте в Twitter или моем репозитории для обратной связи.
Меня всегда интересовали подробности процесса разработки других продуктов, особенно их гайдлайны и подход к использованию CSS. Учитывая мою склонность к деталям чужого CSS кода, я решил написать о подходе к CSS в GitHub.
Несколько фактов
Обзор нашего текущего состояния CSS:
- В качестве препроцессора мы используем SCSS.
- У нас есть более 100 отдельных исходных файлов стилей, которые мы компилируем перед выкаткой в продашн.
- Исходники компилируются в 2 отдельных CSS файла (чтобы избежать проблемы с максимальным количеством селекторов для IE<10).
- Эти 2 файла весят в сумме около 90 kb.
- Мы не используюм какую-нибудь особенную «CSS архитектуру».
- Для определения размера мы выбрали пиксели, но все же у нас есть немного «em-ов».
- Мы используем Normalize.css, смешанный с несколькими нашими собственными стилями для сброса свойств.
Препроцессор
Как уже было упомянуто выше, мы используем SCSS. Этот выбор был сделан еще до того, как я стал принимать участие в разработке, но я с ним согласен (несмотря на то, что Bootstrap написан на LESS). Наш SCSS компилируется и подключается с помощью Rails asset pipeline и Sprockets (на данный момент). Подробнее будет описано ниже.
Как на счет LESS, или Stylus, или ...? Я не думаю, что GitHub когда-нибудь перейдет на LESS. Мы не хотели бы что-то менять в этом отношении, так как нет никаких очевидных преимуществ.
Почему препроцессор? Наш внутренний фреймворк включает в себя набор переменных (таких как шрифты и фирменные цвета) и примесей (в основном для префиксов), которые делают процесс написание кода быстрее и проще. В настоящий момент мы не используем Autoprefixer, но нам следовало бы сделать это. Так мы моглибы свести на нет все наши существующие примеси. Надеюсь, мы осуществим это в ближайшее время.
Мы также не используем source maps, но скоро это изменится. (Для тех, кто не знает, source maps позволяют увидеть в отладчике, к какому из исходных SCSS файлов относится конкретный набор стилей, в отличие от скомпилированных и минифицированных файлов. Они потрясающие.)
Мы используем инструменты SCSS довольно ограниченно. У нас есть переменные для определения цветов, примеси, функции для работы с цветом, математические функции и уровни вложенности. Нам не требуется перебирать классы, создавать глобальные настройки или что-то подобное. Мне нравится простота, которая у нас получилась.
Архитектура
Обычно архитектура CSS представляет из себя BEM или OOCSS. Мы склоняемся к OOCSS, но какого-то целостного подхода у нас нет. Наши основные правила это:
- Избегать необязательных вложений
- Использовать (одиночные) тире при именовании классов
- Писать как можно меньше, чтобы не вносить путанницу
- Я напишу о предпочитаемой мною CSS архитектуре в другой статье. В данный момент я описываю подход GitHub, который хоть и не является идеальным, служит своей цели достаточно хорошо.
Анализ кода
Еще несколько недель назад мы не использовали анализаторы кода. У нас было несколько общих соглашений, но каждый разработчик имел свой собственный стиль, и форматирование каждого из нас было несколько уникальным. На данный момент каждая сборка проходит процесс анализа SCSS кода и падает если:
В CSS описан класс, который не используется в шаблонах app/views/.
Один и тот же селектор используется несколько раз (так как они должны быть всегда скомбинированы).
Нарушены основные правила форматирования (предельная вложенность, разрывы строк между наборами правил и др.)
В целом, есть несколько правил, которые позволяют держать нашу кодовую базу достаточно опрятной. Они не учитывают расхождения в стиле комментирования или архитектуру, но это именно то, что нужно каждой команде. И каждый из нас может предложить и улучшить что-либо.
Два пакета
CSS проекта GitHub состоит из 2х файлов: github и github2. Данное разделение было добавлено несколько лет назад, для решения проблемы работы с IE, который ограничивает количество селекторов до 4,095 на 1 файл. Данное ограничение распространяется на IE 9 версии и ниже. Из-за того, что требованием GitHub является минимум IE9, нам приходится разделять файлы.
По состоянию на сегодняшний день, наши 2 файла состоят примерно из 7000 селекторов. Как это соотносится с другими сайтами?
- Bootstrap v3.2.0 — менее 1,900 селекторов
- Twitter — менее 8,900 селекторов
- NY Times — менее 2,100 селекторов
- SoundCloud — только под 1,100 селекторов (Отредактировно: Ранее я говорил о 7,400, но это было старый SoundCloud)
Эти данные были собраны с помощью cssstats.com. Это небольшой инструмент, который смотрит на ваш CSS под таким углом, под которым большинство людей, включая меня, обычно этого не делают. Также у нас в GitHub есть графики, которые мы используем в собственных целях.
Подключение через Sprockets
В GitHub CSS и JavaScript, подлючается с помощью Sprockets и require. Мы храним оба наших CSS пакета в отдельных директориях внутри app/assets/stylesheets. Вот так это выглядит:
/* = require primer/basecoat/normalize = require primer/basecoat/base = require primer/basecoat/forms = require primer/basecoat/type = require primer/basecoat/utility = require_directory ./shared = require_directory ./_plugins = require_directory ./graphs = require primer-user-content/components/markdown = require primer-user-content/components/syntax-pygments = require primer/components/buttons = require primer/components/navigation = require primer/components/behavior = require primer/components/alerts = require primer/components/tooltips = require primer/components/counter = require primer-select-menu = require octicons = require_directory . */
Мы подключаем наши зависимости (Primer — это наш внутренний фреймворк) и затем загружаем все файлы из директории scss. Какой будет порядок подключения решает Sprockets (мне кажется, что алфавитный). Легкость, c которой мы можем подключать наши таблицы стилей (простым прописыванием require_directory) поражает. Но у этого подхода есть свои минусы.
Порядок применения стилей играет важную роль. Из-за использования Sprockets у нас иногда возникают специфические проблемы. Это происходит потому, что новые файлы могут быть добавлены в любой пакет в любое время. В зависимости от имени файла, новые стили могут появится в разных местах в скомпилированном CSS.
Кроме того, используя Sprocket, вы не имеете немедленного и автоматического доступа к глобальных переменных и примесям в ваших SCSS файлах. Это значит, что вам придется импортировать их явно в начале каждого файла, который ссылается на переменную или примесь.
Производительность
У нас есть огромное количество графиков для мониторинга работы сайты и нашего API. В том числе мы отслеживаем некоторые инересные статистики по фронтенду. К примеру, размер двух наших CSS пакетов за последние 3 месяца:
Также мы отслеживаем количество селекторов на странице. Перед нами по-прежнему стоит задача уменьшить количество селекторов по тегу.
Так как мы регулярно обновляем наш CSS и делаем это множество раз каждый день, нам приходится постоянно сбрасывать кеширование наших довольно больших файлов. Пока что мы не сильно продвинулись в оптимизации размера этих файлов и ограничения сбрасывания кеша, но мы уже начали задумываться об этом более серьезно. Было бы неплохо иметь основной пакет, который изменяется редко, и второстепенный, често изменяемый.
Когда я работал в Twitter, у нас было 2 пакета (не уверен, что это все еще так), основной и дополнительный. В основном были описаны все стили, которые требовались, чтобы отобразить первый твит как можно быстрее. Все остальное хранилось в дополнительном. Учитывая любовь GitHub ко всему быстрому, это как раз то, что мы планируем рассмотреть в ближайшее время. В настоящее время разделение на файлы является случайным.
Как правило, мы не занимаемся производительностью селекторов. Мы знаем о плохих практиках — большая вложенность, использование селекторов по id и элементу и др., но мы не пытаемся через чур оптимиризовать это. Единственным исключением является страница «diff»'а. В связи с обширной разметкой, требуемой для отрисовки diff-a, мы избегаем селекторы атрибутов, такие как [class^=«octicon»]. Если использовать их слишком часто, такие селекторы по атрибутам могут положить браузер (и делали это).
Для любопытных, Jon Rohan, разработчик GitHub, делал отличный доклад о производительности CSS в GitHub, который раскрывает эти проблемы.
Документация
Говоря о документации, мы проделали отличную работу над ней, но все еще работаем над внесением улучшений в нее. Мы выложили в публичный доступ наш CSS гайд и все наши основные правила по написанию CSS. Также мы выложили примеры большинства наших компонентов. Она собрана с помощью KSS, генератора style-гайдов.
Наша документация не идеальна, но она помогает людям найти и использовать, то что они хотят. Кроме того, это отличный способ показать новобранцам то, как мы работаем, чтобы ускорить их вливание в процесс разработки (как это было со мной около 2-х лет назад).
Primer
Я ссылался на Primer ранее, но для тех, кто не знает поясню: Primer — это наш внутренний фреймворк, который содержит стили и компоненты, используемые как в публичных, так и в наших внутренних проектах. Он включает в себя:
- Normalize
- Глобальные стили для box-sizing, типографике, ссылок и др.
- Элементы навигации
- Формы
- Сетки
- Кастомный элемент select
Мы используем его на GitHub.com, Gist и нескольких внутренних приложениях. Как правило, если что-то может быть использовано в другом приложении, мы включаем это в Primer. Большинство компонентов Primer'а задокументированы в нашем гайде.
Рефакторинг
В наших проектах присутствует некоторое количество легаси кода, и CSS входит в него. В отличие от оперсорсных проектов со строгими правилами версионирования, мы часто забиваем на это. Мы принимаем решение об удалении части кода в двух случаях:
- Вручную находим места, которые выглядят схоже, но описываются разным HTML или CSS кодом. В этом случае мы просто объединяем их.
- Запускаем скрипт, который ищет классы в CSS коде, которые отсутствуют во вьюшках. (Сейчас мы автоматизировали этот процесс, включив его в наши тесты).
Сам процесс рефакторинга CSS в GitHub не является уникальным. Мы находим плохой код, удаляем его и выкатываем как можно быстрее. Удалить код может любой участник команды. К нашей команде присоединяется множество крутых разработчиков, но у нас есть и нерды, которые следят за тем, что можно удалить, а что нет.
Вопросы?
Если у вас есть вопросы по этой статье, Bootstrap, GitHub или еще о чем то, спрашивайте в Twitter или моем репозитории для обратной связи.