Анонсируем Dart Sass
В течение нескольких последних месяцев мы тихо работали надо новым проектом. Сегодня я готова анонсировать Dart Sass всему миру. Это абсолютно новая реализация Sass, созданная, чтобы быть быстрой и легкой в установке и разработке. Она еще не завершена — я веду работу по приведению её в соответствие со спецификацией Sass — так что сегодня я просто публикую версию 1.0.0-alpha.1. Но она достаточно надежна, чтобы можно было скачать, поиграться с ней и начать сообщать баги.
Зачем переписывать 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 больше не будет обязана быть строго совместима с последней версией языка, перед запуском этой самой версии, поскольку она больше не будет единственной версией с разумной производительностью.
Ruby Sass в конечном итоге уйдет совсем, если не появится новый разработчик для него. Мы не хотим делать переход внезапным, рискуя расколоть экосистему: я и Крис собираемся поддерживать его в течение одного года, что включает поддержку функциональности на том же уровне, что будет добавляться в Dart Sass. Если кто-то заинтересован в участии как разработчик после этого периода, мы будем рады познакомить его с кодом в течение наступающего года. А если никто не выступит, то Ruby Sass будет официально признан устаревшим и неподдерживаемым.
Я хочу подчеркнуть, что мы не совершаем решение прекратить разработку Ruby Sass просто так. Это большое и не простое для меня изменение, я непрерывно работала над ним почти 10 лет, и мне сложно позволить уйти этой истории. Но мы с Крисом тщательно это обсудили и склонились к тому, что это правильный ход. Мы посвятили так много времени Sass, что это больше не имеет смысла тратить это время на реализацию, медленную настолько, что это неприемлемо для наших крупнейших пользователей.
Что дальше
Перед тем как мы выпустим первую стабильную версию Dart Sass, есть несколько больших вещей в нашем списке:
Достаточно близкая совместимость с render() из node-sass. Этот API является основной точкой входа в LibSass в мире JavaScript. Именно так системы сборки запускают Sass, пользователи определяют свои собственные Sass-функции и Eyeglass передает свои модули в Sass. Мы хотим поддержать API с достаточной мере, чтобы существующая экосистема работала с Dart Sass.
Здесь еще несколько пунктов, которые мы хотели бы сделать в конечном счете, как например поддержка 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. Преимущества такие больше большие и ощутимые, что я уверена, что он стоят издержек.
Dart sass что это
A Dart implementation of Sass. Sass makes CSS fun again.
There are a few different ways to install and run Dart Sass, depending on your environment and your needs.
From Chocolatey or Scoop (Windows)
If you use the Chocolatey package manager or the Scoop package manager for Windows, you can install Dart Sass by running
That’ll give you a sass executable on your command line that will run Dart Sass. See the CLI docs for details.
From Homebrew (macOS)
If you use the Homebrew package manager for macOS, you can install Dart Sass by running
That’ll give you a sass executable on your command line that will run Dart Sass.
You can download the standalone Dart Sass archive for your operating system—containing the Dart VM and the snapshot of the executable—from the GitHub release page. Extract it, add the directory to your path, restart your terminal, and the sass executable is ready to run!
See below for details on Dart Sass’s JavaScript API.
Dart users also have access to more in-depth APIs via the sass_api package. This provides access to the Sass AST and APIs for resolving Sass loads without running a full compilation. It’s separated out into its own package so that it can increase its version number independently of the main sass package.
Assuming you’ve already checked out this repository:
When installed via npm, Dart Sass supports a JavaScript API that’s fully compatible with Node Sass (with a few exceptions listed below), with support for both the render() and renderSync() functions. See the Sass website for full API documentation!
Note however that renderSync() is more than twice as fast as render() due to the overhead of asynchronous callbacks. Both render() and renderSync() support the following options:
No support is intended for the following options:
Dart Sass has replaced Ruby Sass as the canonical implementation of the Sass language. We chose Dart because it presented a number of advantages:
It’s fast. The Dart VM is highly optimized, and getting faster all the time (for the latest performance numbers, see perf.md ). It’s much faster than Ruby, and close to par with C++.
It’s portable. The Dart VM has no external dependencies and can compile applications into standalone snapshot files, so we can distribute Dart Sass as only three files (the VM, the snapshot, and a wrapper script). Dart can also be compiled to JavaScript, which makes it easy to distribute Sass through npm, which the majority of our users use already.
It’s easy to write. Dart is a higher-level language than C++, which means it doesn’t require lots of hassle with memory management and build systems. It’s also statically typed, which makes it easier to confidently make large refactors than with Ruby.
It’s friendlier to contributors. Dart is substantially easier to learn than Ruby, and many Sass users in Google in particular are already familiar with it. More contributors translates to faster, more consistent development.
For the most part, Dart Sass follows semantic versioning. We consider all of the following to be part of the versioned API:
Because Dart Sass has a single version that’s shared across the Dart, JavaScript, and standalone distributions, this may mean that we increment the major version number when there are in fact no breaking changes for one or more distributions. However, we will attempt to limit the number of breaking changes we make and group them in as few releases as possible to minimize churn. We strongly encourage users to use the changelog for a full understanding of all the changes in each release.
There is one exception where breaking changes may be made outside of a major version revision. It is occasionally the case that CSS adds a feature that’s incompatible with existing Sass syntax in some way. Because Sass is committed to full CSS compatibility, we occasionally need to break compatibility with old Sass code in order to remain compatible with CSS.
In these cases, we will first release a version of Sass that emits deprecation warnings for any stylesheets whose behavior will change. Then, at least three months after the release of a version with these deprecation warnings, we will release a minor version with the breaking change to the Sass language semantics.
In general, we consider any change to Dart Sass’s CSS output that would cause that CSS to stop working in a real browser to be a breaking change. However, there are some cases where such a change would have substantial benefits and would only negatively affect a small minority of rarely-used browsers. We don’t want to have to block such a change on a major version release.
As such, if a change would break compatibility with less than 2% of the global market share of browser according to StatCounter GlobalStats, we may release a minor version of Dart Sass with that change.
We consider dropping support for a given version of Node.js to be a breaking change as long as that version is still supported by Node.js. This means that releases listed as Current, Active LTS, or Maintenance LTS according to the Node.js release page. Once a Node.js version is out of LTS, Dart Sass considers itself free to break support if necessary.
Behavioral Differences from Ruby Sass
There are a few intentional behavioral differences between Dart Sass and Ruby Sass. These are generally places where Ruby Sass has an undesired behavior, and it’s substantially easier to implement the correct behavior than it would be to implement compatible behavior. These should all have tracking bugs against Ruby Sass to update the reference behavior.
Subject selectors are not supported. See issue 1126.
Pseudo selector arguments are parsed as s rather than having a more limited custom parsing. See issue 2120.
The numeric precision is set to 10. See issue 1122.
The indented syntax parser is more flexible: it doesn’t require consistent indentation across the whole document. See issue 2176.
Colors do not support channel-by-channel arithmetic. See issue 2144.
rgba() and hsla() alpha values with percentage units are interpreted as percentages. Other units are forbidden. See issue 1525.
Too many variable arguments passed to a function is an error. See issue 1408.
Allow @extend to reach outside a media query if there’s an identical @extend defined outside that query. This isn’t tracked explicitly, because it’ll be irrelevant when issue 1050 is fixed.
Some selector pseudos containing placeholder selectors will be compiled where they wouldn’t be in Ruby Sass. This better matches the semantics of the selectors in question, and is more efficient. See issue 2228.
The old-style :property value syntax is not supported in the indented syntax. See issue 2245.
The reference combinator is not supported. See issue 303.
Universal selector unification is symmetrical. See issue 2247.
@extend doesn’t produce an error if it matches but fails to unify. See issue 2250.
Dart Sass currently only supports UTF-8 documents. We’d like to support more, but Dart currently doesn’t support them. See dart-lang/sdk#11744, for example.
Disclaimer: this is not an official Google product.
About
The reference implementation of Sass, written in Dart.
Интерфейс командной строки Dart Sass
Применение permalink Применение
Исполняемый файл Dart Sass можно запускать в одном из двух режимов.
Режим “один к одному” permalink Режим “один к одному”
В режиме «один к одному» один входной файл ( input.scss ) компилируется в единственное место вывода ( output.css ). Если расположение вывода не передано, скомпилированный CSS выводится на терминал.
Режим “многие ко многим” permalink Режим “многие ко многим”
В режиме «многие-ко-многим» один или несколько входных файлов компилируются в один или несколько выходных файлов. Входы отделяются от выходов двоеточиями. Он также может компилировать все файлы Sass в каталоге в файлы CSS с такими же именами в другом каталоге.
Опции permalink Опции
Ввод и Вывод permalink Ввод и Вывод
Эти параметры управляют тем, как Sass загружает свои входные файлы и как создает выходные файлы.
Исходные карты permalink Исходные карты
Dart Sass по умолчанию генерирует исходные карты для каждого создаваемого файла CSS.
Другие опции permalink Другие опции
Этот флаг указывает Sass немедленно прекратить компиляцию при обнаружении ошибки, а не пытаться скомпилировать другие файлы Sass, которые могут не содержать ошибок. В основном это полезно в режиме многие-ко-многим.
Этот флаг сообщает Sass о необходимости распечатать полную трассировку стека Dart или JavaScript при обнаружении ошибки. Команда Sass использует его для отладки ошибок.
Announcing Dart Sass
Posted 31 October 2016 by Natalie Weizenbaum
Why Rewrite Sass? permalink Why Rewrite Sass?
Over the past few years, there have been two primary implementations of Sass. Ruby Sass was the original, written mostly by me with substantial help from Chris. It’s high-level and easy to hack on, so it’s where we iterate on new features and where they first get released. Then there’s LibSass, the C++ implementation, originally created by Aaron and Hampton and now maintained by Marcel and Michael. It’s low-level, which makes it very fast and easy to install and embed in other languages. In particular, its Node.js bindings are a very popular way to use Sass in the JavaScript world.
Without two people’s worth of effort, we were no longer sure that LibSass could keep pace with the speed Chris and I wanted to introduce changes into the language. And it had been clear for a long time that Ruby Sass was far too slow for use cases involving large stylesheets. We needed a new implementation, one that could generate CSS quickly and add new features quickly.
Why Dart? permalink Why Dart?
At the same time, Dart is easy to work with—much more so than C++, and to some extent even more than Ruby for such a large project. Granted, not as many people are familiar with it as with JavaScript, but language implementations don’t tend to get many external contributions anyway. I’ll be doing most of the work on the new implementation, and Dart is the language that I’m personally most comfortable with at the moment (when I’m not working on Sass, I’m on the Dart team). Using Dart gives me a lot of extra velocity.
Unlike Ruby or JavaScript, Dart is statically typed, so every value’s type can be figured out without running the code. Unlike C++, it’s garbage collected, so we don’t have to worry as much about cleaning up after ourselves. This makes it easy to write, easy to modify, and easy to maintain. Maybe even more importantly, it makes it easy to translate to other programming languages, which will help LibSass get new features faster.
What Will Happen to The Other Implementations? permalink What Will Happen to The Other Implementations?
More flexibility translates into faster LibSass releases that prioritize the features users want most. Strict compatibility meant that important features like CSS custom property support can’t be released until all the tiny tricky edge cases that were in the corresponding Ruby Sass release, like :root unification, are implemented as well. We’ll still strive for as much compatibility as possible, but we won’t let that stand in the way of velocity.
Ruby Sass, on the other hand, will eventually go away unless a new maintainer appears. We don’t want to make the transition sudden and risk fracturing the ecosystem: Chris and I are committed to maintaining it for one year, which includes keeping the language in sync with any new additions in Dart Sass. If anyone is interested in volunteering as a maintainer after that period, we’d be thrilled to mentor them and teach them the codebase over the coming year. But if no one steps up, Ruby Sass will be officially considered deprecated and unmaintained.
I want to emphasize that we aren’t making the decision to stop developing Ruby Sass lightly. This is a big change, and it’s not an easy one for me—I’ve worked on Ruby Sass continuously for almost ten years now, and it’s difficult to let that history go. But Chris and I have discussed this thoroughly, and we’re convinced this is the right move. We only have so much time to devote to Sass, and it no longer makes sense to put that time into an implementation that’s so slow as to be infeasible for many of our largest users.
What Next? permalink What Next?
Before we release the first stable version of Dart Sass, there are a few big things on our to-do list:
Dart Sass compatibility in Ruby Sass. There are some cases where Dart Sass intentionally differs from Ruby Sass, particularly when Ruby Sass’s behavior is considered a bug. We should add deprecation messages in Ruby Sass and, if we can do so with minimal disruption, add support for the new behavior.
Onward Into the Future permalink Onward Into the Future
The next couple months will see a lot of work go into getting Dart Sass stable and compatible, and getting Sass 3.5 features into LibSass. I think it’s likely that early 2017 will see a stable release of Dart Sass and a 3.5 release of LibSass. At that point we’ll set our sight on the big features and start working towards Sass 4.0 and its brand new module system.
Dart Sass is a big change, but it’s an exciting one as well. It’ll allow us to get new features into users’ hands faster, and to make those features run faster. It’ll make it possible for users to trivially install and run the reference implementation. And it’ll give us a performant way to run Sass in pure JavaScript Sass for the first time ever. The benefits are large and tangible, and I’m confident they’re worth the costs.
I say “officially” because he’s still contributing to the project when he can, just not in an official maintainer capacity. ↩
Caveats apply: I’m not a benchmarking expert, and these tests were ad hoc and run against non-representative source stylesheets. If anyone is interested in working on more scientific benchmarks, please let me know! ↩
Sass © 2006–2021 the Sass team, and numerous contributors. It is available for use and modification under the MIT License.



