sass.js

repository·master·Indexed 22 days ago

https://github.com/medialize/sass.js

A JavaScript-based Sass parser and convenience API for an emscripted version of libsass (v3.6.2). It allows compiling SCSS and SASS to CSS in environments where native binaries are unavailable, such as web browsers. The library features a Worker API for non-blocking compilation, a virtual file system for @import resolution, and a Node.js utility for local file system compilation.

Tokens
6K
Snippets
23
Records
25
Agent score
77%

What's inside sass.js

  1. Overview of Sass.js

    master

    Sass.js is a Sass parser implemented in JavaScript. It provides a convenience API for an emscripted version of libsass (v3.6.2). It is primarily intended for environments where running a native binary is not feasible, such as the browser.

    Important Considerations:

    • Performance: If you are running in a Node.js environment, use node-sass instead, as it is considerably faster.
    • Bundle Size: The minified worker is approximately 4.5MB (827KB gzipped).
  2. How Sass.js resolves file names

    master

    When you use @import "hello/world";, Sass.js (via libsass) attempts to resolve the path using the following priority order:

    1. hello/world (as given)
    2. hello/_world (underscore prefix)
    3. hello/_world.scss (underscore + extension)
    4. hello/_world.sass (underscore + alternative extension)
    5. hello/_world.css (underscore + css extension)
    6. hello/world.scss (given + extension)
    7. hello/world.sass (given + alternative extension)
    8. hello/world.css (given + css extension)

    In the Synchronous API (sass.sync.js), you can use Sass.findPathVariation to find the correct file on your local disk using a stat function (like fs.statSync).

    var fs = require('fs');
    var Sass = require('sass.js');
    
    // Find which variation exists on the real file system
    var file = Sass.findPathVariation(fs.statSync, 'hello/world');
  3. Understand the compilation response object

    master

    The callback for compile and compileFile receives a result object. The structure depends on whether the compilation succeeded or failed.

    Success (status: 0)

    • status: 0 (indicates success)
    • text: The compiled CSS string.
    • map: The SourceMap object (if enabled).
    • files: An array of files used during compilation.

    Error (status != 0)

    • status: Non-zero value.
    • file: The file where the error occurred.
    • line: The line number of the error.
    • column: The column number of the error.
    • message: A short error description.
    • formatted: A human-readable, multi-line string containing the error context and a pointer to the problematic code.
    // Example Success Object
    {
      "status": 0,
      "text": ".some-selector { width: 123px; }\n",
      "map": { ... },
      "files": []
    }
    
    // Example Error Object
    {
      "status": 1,
      "file": "stdin",
      "line": 7,
      "column": 1,
      "message": "invalid top-level expression",
      "formatted": "Error: invalid top-level expression\n        on line 7 of stdin\n>> bad-token-test\n   ^\n"
    }
  4. Compile files from the file system in Node.js

    master

    For an easier workflow in Node.js, use dist/sass.node.js. This utility handles reading files from the local file system and importing them into emscripten's memory so they can be processed by libsass. It provides a convenience function that accepts a file path instead of a string of SCSS code.

    var compile = require('sass.js/dist/sass.node');
    
    var path = 'scss/example.scss';
    var options = {
      style: compile.Sass.style.expanded,
    };
    
    compile(path, options, function(result) {
      console.log(result);
    });
  5. Build Sass.js from source

    master

    To compile libsass to JS, you must have docker installed. Follow these steps to prepare the environment and build the full library.

    1. Preparations

    Clone the repository and install dependencies:

    git clone git@github.com:medialize/sass.js.git
    cd sass.js
    npm install

    2. Build the full library

    Run the build command to generate all distribution files:

    npm run build

    Build Outputs (dist/):

    • dist/file-size.json
    • dist/sass.js
    • dist/sass.node.js
    • dist/sass.sync.js
    • dist/sass.worker.js
    • dist/versions.json
    npm install
    npm run build
  6. Use Sass.js in Node.js

    master

    To run Sass.js in Node.js, use the synchronous API by requiring sass.js. Note that this will run synchronously in the main thread.

    var Sass = require('sass.js');
    var scss = '$someVar: 123px; .some-selector { width: $someVar; }';
    Sass.compile(scss, function(result) {
      console.log(result);
    });
  7. Use Sass.js in the browser with Web Workers

    master

    The recommended way to run Sass.js in a browser is using the asynchronous Web Worker API. This prevents the compiler from blocking the main thread. You must include dist/sass.js and then instantiate a new Sass object to call .compile().

    <script src="dist/sass.js"></script>
    <script>
      var sass = new Sass();
      var scss = '$someVar: 123px; .some-selector { width: $someVar; }';
      sass.compile(scss, function(result) {
        console.log(result);
      });
    </script>
  8. Configure the worker URL for module loaders

    master

    When using a module loader (like RequireJS, Browserify, or Webpack), dist/sass.js cannot automatically locate the worker file. You must manually specify the path to dist/sass.worker.js using Sass.setWorkerUrl(). The URL should be relative to the document URL.

    // load Sass.js
    var Sass = require('path/to/sass.js');
    
    // tell Sass.js where it can find the worker,
    // url is relative to document.URL
    Sass.setWorkerUrl('path/to/dist/sass.worker.js');
    
    // initialize a Sass instance
    var sass = new Sass();
    
    var scss = '$someVar: 123px; .some-selector { width: $someVar; }';
    sass.compile(scss, function(result) {
      console.log(result);
    });
  9. Compile SCSS/SASS files in Node.js

    master

    When working in a Node.js environment, you can use the sass.node.js utility to compile files directly from your real local file system. This utility handles the complexity of reading files from your disk and writing them into the Emscripten virtual file system before compilation.

    Note: All paths provided must be relative to (and descendants of) the current working directory (process.cwd()).

    var compile = require('sass.js/dist/sass.node');
    
    var path = 'scss/example.scss';
    var options = {
      style: compile.Sass.style.expanded,
    };
    
    compile(path, options, function(result) {
      console.log(result);
    });
  10. Initialize a Sass instance using the Worker API

    master

    When using dist/sass.js, you must initialize a Sass instance by providing the path to the worker file. You can also set a global worker URL to avoid passing the path to every constructor.

    To clean up resources, call .destroy() on your instance.

    // initialize a Sass instance
    var sass = new Sass('path/to/sass.worker.js');
    
    // destruct/destroy/clean up a Sass instance
    sass.destroy();
    
    // Alternatively, set the worker URL globally
    Sass.setWorkerUrl('path/to/sass.worker.js');
    var sass = new Sass();
  11. Compile multiple sources in parallel using the Worker API

    master

    By default, calling .compile() on a single Sass instance processes requests in sequence. To achieve parallel compilation, instantiate multiple Sass objects. This is most efficient when using Sass.setWorkerUrl() to avoid repeating the worker path.

    // Parallel compilation pattern
    Sass.setWorkerUrl('path/to/sass.worker.js');
    
    var sass1 = new Sass();
    var sass2 = new Sass();
    
    sass1.compile(source1, callback1);
    sass2.compile(source2, callback2);
  12. Use the Synchronous API in the browser

    master

    If you are in an environment that does not support Web Workers, you can use dist/sass.sync.js. This runs the compiler in the main thread (EventLoop), which is not recommended as it blocks execution. The synchronous API uses a singleton pattern and does not require Sass.setWorkerUrl().

    <script src="dist/sass.sync.js"></script>
    <script>
      var scss = '$someVar: 123px; .some-selector { width: $someVar; }';
      Sass.compile(scss, function(result) {
        console.log(result);
      });
    </script>