{"id":295393,"date":"2019-09-17T07:19:18","date_gmt":"2019-09-17T14:19:18","guid":{"rendered":"https:\/\/css-tricks.com\/?p=295393"},"modified":"2019-10-09T10:06:32","modified_gmt":"2019-10-09T17:06:32","slug":"a-proof-of-concept-for-making-sass-faster","status":"publish","type":"post","link":"https:\/\/css-tricks.com\/a-proof-of-concept-for-making-sass-faster\/","title":{"rendered":"A Proof of Concept for Making Sass Faster"},"content":{"rendered":"

At the start of a new project, Sass compilation happens in the blink of an eye. This feels great, especially when it\u2019s paired with Browsersync, which reloads the stylesheet for us in the browser. But, as the amount of Sass grows, compilation time increases. This is far from ideal.<\/p>\n

It can be a real pain when the compilation time creeps over one or two seconds. For me, that’s enough time to lose focus at the end of a long day. So, I would like to share a solution that’s available in a WordPress CSS Editor<\/a> called Microthemer, as a proof of concept. <\/p>\n

This is a two-part article. The first part is for the attention of Sass users. We will introduce the basic principles, performance results, and an interactive demo. The second part covers the nuts and bolts of how Microthemer makes Sass faster. And considers how to implement this as an npm package that can deliver fast, scalable Sass to a much broader community of developers.<\/p>\n

<\/p>\n

How Microthemer compiles Sass in an instant<\/h3>\n

In some ways, this performance optimisation is simple. Microthemer just compiles less Sass code. It doesn\u2019t intervene with Sass\u2019 internal compilation process.<\/p>\n

In order to feed the Sass compiler less code, Microthemer maintains an understanding of Sass entities used throughout the code base, like variables and mixins. When a selector is edited, Microthemer only compiles that single selector, plus any related selectors. Selectors are related if they make use of the same variables for instance, or one selector extends another. With this system, Sass compilation remains as fast with 3000 selectors as it does with a handful.<\/p>\n

Performance results<\/h3>\n

With 3000 selectors, the compile time is around 0.05 seconds. It varies, of course. Sometimes it might be closer to 0.1 seconds. Other times the compilation happens as fast as 0.01 seconds (10ms).<\/p>\n

To see for yourself, you can watch a video demonstration.<\/a> Or mess around with the online Microthemer playground (see instructions below).<\/p>\n

Online Microthemer playground<\/h3>\n

The online playground makes it easy to experiment with Microthemer yourself.<\/p>\n

Instructions<\/h4>\n
    \n
  1. Go to the online Microthemer playground<\/a>.<\/li>\n
  2. Enable support for Sass via General \u2192 Preferences \u2192 CSS \/ SCSS \u2192 Enable SCSS<\/samp>.<\/li>\n
  3. Go to View \u2192 full code editor \u2192 on<\/samp> to add global variables, mixins, and functions.<\/li>\n
  4. Switch back to the main UI view (View \u2192 full code editor \u2192 off<\/samp>).<\/li>\n
  5. Create selectors via the Target button.<\/li>\n
  6. Add Sass code via the editor to the left of the Font property group.<\/li>\n
  7. After each change, you can see what code Microthemer included in the compile process via View \u2192 Generated CSS \u2192 Previous SCSS compile<\/samp>.<\/li>\n
  8. To see how this works at scale, you can import vanilla CSS from a large stylesheet into Microthemer via Packs \u2192 Import \u2192 CSS stylesheet<\/samp> (importing Sass isn’t supported – yet). <\/li>\n<\/ol>\n

    Do you want this as an npm package?<\/h3>\n

    Microthemer\u2019s selective compilation technique could also be delivered as an npm package. But the question is, do you see a need for this? Could your local Sass environment do with a speed boost? If so, please leave a comment below. <\/p>\n

    The rest of this article is aimed at those who develop tools for the community. As well as those who might be curious about how this challenge was tackled. <\/p>\n

    The Microthemer way to compile Sass<\/h3>\n

    We will move on to some code examples shortly. But first, let’s consider the main application goals.<\/p>\n

    1. Compile minimal code<\/h4>\n

    We want to compile the one selector being edited if it has no relationship with other selectors, or multiple selectors with related Sass entities — but no more than necessary.<\/p>\n

    2. Responsive to code changes<\/h4>\n

    We want to remove any perception of waiting for Sass to compile. We also don’t want to crunch too much data between user keystrokes. <\/p>\n

    3. Equal CSS output<\/h4>\n

    We want to return the same CSS a full compile would generate, but for a subset of code.<\/p>\n

    Sass examples<\/h3>\n

    The following code will serve as a point of reference throughout this article. It covers all of the scenarios our selective compiler needs to handle. Such as global variables, mixin side-effects, and extended selectors.<\/p>\n

    Variables, functions, and mixins<\/h4>\n
    $primary-color: green;\r\n$secondary-color: red;\r\n$dark-color: black;\r\n\r\n@function toRem($px, $rootSize: 16){\r\n  @return #{$px \/ $rootSize}rem;\r\n}\r\n\r\n@mixin rounded(){\r\n  border-radius: 999px;\r\n  $secondary-color: blue !global;\r\n}<\/code><\/pre>\n

    Selectors<\/h4>\n
    .entry-title {\r\n  color: $dark-color;\r\n}\r\n\r\n.btn {\r\n  display: inline-block;\r\n  padding: 1em;\r\n  color: white;\r\n  text-decoration: none;\r\n}\r\n\r\n.btn-success {\r\n  @extend .btn;\r\n  background-color: $primary-color;\r\n  @include rounded;\r\n}\r\n\r\n.btn-error {\r\n  @extend .btn;\r\n  background-color: $secondary-color;\r\n}\r\n\r\n\/\/ Larger screens\r\n@media (min-width: 960px) {\r\n  .btn-success {\r\n    border:4px solid darken($primary-color, 10%);\r\n    &::before {\r\n      content: \"\\2713\"; \/\/ unicode tick\r\n      margin-right: .5em;\r\n    }\r\n  }\r\n}<\/code><\/pre>\n

    The Microthemer interface<\/h3>\n

    Microthemer has two main editing views. <\/p>\n

    View 1: Full code<\/h4>\n

    We edit the full code editor in the same way as a regular Sass file. That\u2019s where global variables, functions, mixins, and imports go.<\/p>\n

    \"\"<\/figure>\n

    View 2: Visual<\/h4>\n

    The visual view has a single selector architecture. Each CSS selector is a separate UI selector. These UI selectors are organized into folders. <\/p>\n

    \"\"<\/figure>\n

    Because Microthemer segments individual selectors, analysis happens at a very granular scale \u2014 one selector at a time. <\/p>\n

    \"\"<\/figure>\n

    Here\u2019s a quick quiz question for you. The $secondary-color<\/code> variable is set to red<\/code> at the top of the full code view. So why is the error button in the previous screenshots blue? Hint: it has to do with mixin side effects. More on that shortly.<\/p>\n

    Third party libraries<\/h3>\n

    A huge thanks to the authors of the following JavaScript libraries Microthemer uses:<\/p>\n