Pull to refresh

GitHub's CSS

Reading time7 min
Views15K
[Прим. перев.]: предлагаю вашему вниманию перевод статьи Марка Отто, разработчика GitHub, бывшего разработчика Twitter, создателя самого известного CSS фреймворка Bootstrap. В этой статье он рассказывает о внутреннем устройстве CSS проектов GitHub.


Меня всегда интересовали подробности процесса разработки других продуктов, особенно их гайдлайны и подход к использованию 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 месяца:
image
Также мы отслеживаем количество селекторов на странице. Перед нами по-прежнему стоит задача уменьшить количество селекторов по тегу.
image
Так как мы регулярно обновляем наш CSS и делаем это множество раз каждый день, нам приходится постоянно сбрасывать кеширование наших довольно больших файлов. Пока что мы не сильно продвинулись в оптимизации размера этих файлов и ограничения сбрасывания кеша, но мы уже начали задумываться об этом более серьезно. Было бы неплохо иметь основной пакет, который изменяется редко, и второстепенный, често изменяемый.

Когда я работал в Twitter, у нас было 2 пакета (не уверен, что это все еще так), основной и дополнительный. В основном были описаны все стили, которые требовались, чтобы отобразить первый твит как можно быстрее. Все остальное хранилось в дополнительном. Учитывая любовь GitHub ко всему быстрому, это как раз то, что мы планируем рассмотреть в ближайшее время. В настоящее время разделение на файлы является случайным.

Как правило, мы не занимаемся производительностью селекторов. Мы знаем о плохих практиках — большая вложенность, использование селекторов по id и элементу и др., но мы не пытаемся через чур оптимиризовать это. Единственным исключением является страница «diff»'а. В связи с обширной разметкой, требуемой для отрисовки diff-a, мы избегаем селекторы атрибутов, такие как [class^=«octicon»]. Если использовать их слишком часто, такие селекторы по атрибутам могут положить браузер (и делали это).

Для любопытных, Jon Rohan, разработчик GitHub, делал отличный доклад о производительности CSS в GitHub, который раскрывает эти проблемы.

Документация


image
Говоря о документации, мы проделали отличную работу над ней, но все еще работаем над внесением улучшений в нее. Мы выложили в публичный доступ наш CSS гайд и все наши основные правила по написанию CSS. Также мы выложили примеры большинства наших компонентов. Она собрана с помощью KSS, генератора style-гайдов.

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

Primer


image
Я ссылался на Primer ранее, но для тех, кто не знает поясню: Primer — это наш внутренний фреймворк, который содержит стили и компоненты, используемые как в публичных, так и в наших внутренних проектах. Он включает в себя:

  • Normalize
  • Глобальные стили для box-sizing, типографике, ссылок и др.
  • Элементы навигации
  • Формы
  • Сетки
  • Кастомный элемент select

Мы используем его на GitHub.com, Gist и нескольких внутренних приложениях. Как правило, если что-то может быть использовано в другом приложении, мы включаем это в Primer. Большинство компонентов Primer'а задокументированы в нашем гайде.

Рефакторинг


В наших проектах присутствует некоторое количество легаси кода, и CSS входит в него. В отличие от оперсорсных проектов со строгими правилами версионирования, мы часто забиваем на это. Мы принимаем решение об удалении части кода в двух случаях:

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

Сам процесс рефакторинга CSS в GitHub не является уникальным. Мы находим плохой код, удаляем его и выкатываем как можно быстрее. Удалить код может любой участник команды. К нашей команде присоединяется множество крутых разработчиков, но у нас есть и нерды, которые следят за тем, что можно удалить, а что нет.

Вопросы?


Если у вас есть вопросы по этой статье, Bootstrap, GitHub или еще о чем то, спрашивайте в Twitter или моем репозитории для обратной связи.
Tags:
Hubs:
Total votes 36: ↑35 and ↓1+34
Comments17

Articles