В течение нескольких последних месяцев мы тихо работали надо новым проектом. Сегодня я готова анонсировать Dart Sass всему миру. Это абсолютно новая имплементация Sass, созданная, чтобы быть быстрой и легкой в установке и разработке. Она еще не завершена — я веду работу по приведению её в соответствие со спецификацией Sass — так что сегодня я просто публикую версию 1.0.0-alpha.1. Но она достаточно надежна, чтобы можно было скачать, поиграться с ней и начать сообщать баги.
Вы можете скачать архив с со страницы релиза — просто распакуйте его, добавьте директорию в path, и запустите dart-sass
. Dart также компилируется в JavaScript, так что если у вас установлен npm, то вы можете установить JS-версию запустив npm install -g dart-sass
. И если вы сами уже являетесь пользователем Dart, то можете его установить через pub global dart-sass
.
Зачем переписывать Sass?
В течение последних нескольких лет было две основные реализации Sass. Ruby Sass был первым, написанным в основном мной при существенной поддержке Криса. Он был высокоуровневым и легким для разработки, и являлся тем местом, где мы обкатывали и выпускали новые возможности. Затем появился LibSass — имплементация на C++, изначально созданная Аароном и Хэмптоном, а в настоящее время поддерживается Марселем и Майклом. Это низкоуровневая версия, что делает ее быстрой и легкой в установке и встраивании в другие языки. В частности, байндинг к Node.js является очень популярным способом использования Sass в мире JavaScript.
Достоинства каждой версии дополняют слабости другой. Там где LibSass быстра и переносима, Ruby Sass медленный и сложный к установке не-Ruby пользователями. Зато Ruby Sass проще в разработке, в то время как в LibSass добавлять новые возможности намного сложнее из-за низкоуровнего языка. Хотя взаимодополняющие отношения могут быть здоровыми, но это так же значит, что ни одно из решений не такое хорошее, каким должно бы быть. Это мы обнаружили, когда в мае Марсель официально покинул команду LibSass. (Примечание автора: Я говорю "официально", потому что он все еще принимает участие в проекте по мере возможности, но не в том объеме как официальный разработчик).
Лишенные усилий двух человек, мы были не уверены, что LibSass сможет поддерживать темп, так что Крис и я захотели внести изменения в используемый язык. В течение долгого времени было понятно, что Ruby Sass намного медленнее при обработке больших таблиц стилей. Нам нужна была новая имплементация, которая могла бы быстро генерировать CSS и быстро добавлять новую функциональность.
Почему Dart?
Мы рассмотрели несколько возможных языков и остановились на Dart по нескольким причинам. Во-первых, он действительно быстрый – Dart-VM в основном сильно быстрее чем JavaScript VM и предварительные бенчмарки показывают, что для больших файлов Dart Sass в 5-10 раз быстрее Ruby Sass и только в 1,5 раза медленнее LibSass. (Примечание автора: Я не эксперт в бенчмарках, и в тестах были подобраны (ad hoc — пер.) нерепрезентативные исходные файлы. Если кто-нибудь заинтересован в работе над более научными измерениями, дайте мне знать). С опаской предположу, что это будет в 1,5-2 раза быстрее специализированной JS-реализации, но не могу сказать уверенно. Кроме того, производительность Dart улучшается со временем.
В то время как с Dart легко работать — намного легче, чем с C++, и в некоторой степени легче чем с Ruby для такого большого проекта. Конечно, не так много людей знакомы с ним, как с JavaScript, но работа над реализацией языка не подразумевает множества внешних участников в любом случае. Я буду делать большую часть работы над новой имплементацией, и Dart это язык с которым я лично чувствую себя комфортно в данный момент (в то время, когда я не работаю над Sass, я в команде Dart). Использование Dart дает мне прибавку в скорости.
В отличие от Ruby или JavaScript, Dart статически типизирован, так что тип каждого значения может быть выведен без необходимости запускать сам код. Также, в отличие от C++, он со сборкой мусора, то есть нам не нужно беспокоиться о приборке за собой. Это делает его легким для написания, правок и поддержки. Может быть, даже более важно то, что он легко транслируется в другие языки программирования, что позволит LibSass получать новые возможности быстрее.
Последняя причина выбора Dart, это то, чем немногие языки могут похвастаться: совместимость с JavaScript. Dart может быть скомпилирован в JavaScript, который может напрямую использоваться в Node.js и даже возможно в браузере. Большая часть экосистемы Sass построена на node-sass, и мы намерены сделать JS-версию Dart Sass как можно более совместимой по API c node-sass, чтобы можно было легко перекинуть на новую версию существующие инструменты и системы сборки.
Единственный недостаток здесь – это провал по скорости: Dart Sass примерно вдвое медленнее при запуске на V8 по сравнению с Dart VM. Однако, он все еще дает уверенный прирост в 3-4 раза по сравнению с Ruby Sass. В итоге, мы также надеемся, что сможем предоставить пользователям JS-версии путь миграции на Dart VM настолько легкий, насколько возможно.
Что же случится с Остальными Имплементациями?
Никаких перемен в разработке LibSass. Майкл напряженно работает над добавлением новых возможностей из Sass 3.5, и мы ожидаем, что этот процесс продолжится по мере добавления новой функциональности. Единственным отличием станет то, что LibSass больше не будет обязана быть строго совместима с последней версией языка, перед запуском этой самой версии, поскольку она больше не будет единственной версией с разумной производительностью.
Больше гибкости выльется в более быстрые релизы LibSass, которые поставят на первый план возможности, которые пользователи хотят сильнее всего. Строгая совместимость значила, что важные нововведения, такие, как, например, поддержка пользовательских CSS-свойств не могут быть выпущены до тех пор, пока не будут обработаны все маленькие и хитрые граничные случаи, которые были в соответствующей версии Ruby Sass, например, объединение :root
. Мы все еще стараемся достигать максимальной совместимости, насколько возможно, но мы не будем позволять стоять ей на пути у скорости.
Ruby Sass в конечном итоге уйдет совсем, если не появится новый разработчик для него. Мы не хотим делать переход внезапным, рискуя расколоть экосистему: я и Крис собираемся поддерживать его в течение одного года, что включает поддержку функциональности на том же уровне, что будет добавляться в Dart Sass. Если кто-то заинтересован в участии как разработчик после этого периода, мы будем рады познакомить его с кодом в течение наступающего года. А если никто не выступит, то Ruby Sass будет официально признан устаревшим и неподдерживаемым.
Я хочу подчеркнуть, что мы не совершаем решение прекратить разработку Ruby Sass просто так. Это большое и не простое для меня изменение, я непрерывно работала над ним почти 10 лет, и мне сложно позволить уйти этой истории. Но мы с Крисом тщательно это обсудили и склонились к тому, что это правильный ход. Мы посвятили так много времени Sass, что это больше не имеет смысла тратить это время на реализацию, медленную настолько, что это неприемлемо для наших крупнейших пользователей.
Что дальше
Перед тем как мы выпустим первую стабильную версию Dart Sass, есть несколько больших вещей в нашем списке:
-
Полная совместимость со спецификацией Sass. Здесь все еще есть моменты, где Dart Sass ведет себя неправильно, особенно в отношении
@extend
. Я не ожидаю никакой особой несовместимости, которую будет трудно решить, спецификация Sass довольно исчерпывающая, так что это лишь дело уменьшения количества непройденных тестов до нуля. -
Достаточно близкая совместимость с
render()
из node-sass. Этот API является основной точкой входа в LibSass в мире JavaScript. Именно так системы сборки запускают Sass, пользователи определяют свои собственные Sass-функции и Eyeglass передает свои модули в Sass. Мы хотим поддержать API с достаточной мере, чтобы существующая экосистема работала с Dart Sass. - Совместимость Dart и Ruby Sass. Здесь есть несколько случаев, где Dart-функциональность намеренно отличается от Ruby, в частности, там где поведение Ruby расценивается как баг. Мы должны добавить предупреждения об этом в Ruby Sass или, если мы сможем это сделать с минимальными правками, внести новое поведение и в Ruby.
Здесь еще несколько пунктов, которые мы хотели бы сделать в конечном счете, как например поддержка Sass в браузере и предоставление node-sass-совместимой обертки для Sass на Dart VM, но это не блокирует начальный релиз.
В дальнейшем будущем
На несколько следующих месяцев я вижу много работы по становлению Dart Sass стабильнее и совместимее, а также добавление возможностей Sass 3.5 в LibSass. Я думаю, что скорее всего в начале 2017 мы увидим стабильный релиз Dart Sass и версию LibSass 3.5. В это время мы определимся с нашим взглядом на крупную функциональность и начнем работать над Sass 4.0 и его совершенно новой системой модулей.
Dart Sass не является большой переменой, но в то же время захватывающей. Это позволит нам быстрее доставлять новую функциональность в руки пользователей, а также заставить эту функциональность работать быстрее. Кроме того, это позволит пользователям легко установить и запустить эталонную имплементацию. И, наконец, это впервые даст нам производительный путь запустить Sass на чистом JavaScript. Преимущества такие больше большие и ощутимые, что я уверена, что он стоят издержек.
Автор: justboris