callumacrae callumacrae - 5 months ago 14
Node.js Question

Importing Sass through npm

Currently in our Sass files we have something like the following:

@import "../../node_modules/some-module/sass/app";


This is bad, because we're not actually sure of the path: it could be
../node_modules
, it could be
../../../../../node_modules
, because of how npm installs stuff.

Is there a way in Sass that we can search up until we find node_modules? Or even a proper way of including Sass through npm?

Answer

You can use a Sass importer function to do so. Cf. https://github.com/sass/node-sass#importer--v200.

The following example illustrates node-sass@3.0.0 with node@0.12.2:

Install the bower dependency:

$ bower install sass-mq
$ npm install sass/node-sass#3.0.0-pre

The Sass file:

@import 'sass-mq/mq';

body {
  @include mq($from: mobile) {
    color: red;
  }
  @include mq($until: tablet) {
    color: blue;
  }
}

The node renderer file:

'use strict';

var sass = require('node-sass');
var path = require('path');
var fs = require('fs');

var options = {
  file: './sample.scss',
  importer: function bowerModule(url, file, done){
    var bowerComponent = url.split(path.sep)[0];

    if (bowerComponent !== url) {
      fs.access(path.join(__dirname, 'bower_components', bowerComponent), fs.R_OK, function(err){
        if (err) {
          return done({ file: url });
        }

        var newUrl = path.join(__dirname, 'bower_components', url);

        done({ file: newUrl });
      })
    }
    else {
      done({ file: url });
    }
  }
};

sass.render(options, function(err, result){
  if (err) {
    console.error(err);
    return;
  }

  console.log(result.css.toString());
});

This one is simple and not recursive. The require.resolve function could help to deal with the tree – or wait until npm@3.0.0 to benefit from the flat dependency tree.

Comments