Импорт Sass через npm

В настоящее время в наших файлах Sass у нас есть что-то вроде следующего:

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

Это плохо, потому что мы на самом деле не уверены в правильности пути: это может быть ../node_modules, может быть ../../../../../node_modules, из-за того, как npm устанавливает материал.

есть ли способ в Sass, который мы можем искать, пока не найдем node_modules? Или даже правильный способ включения Sass через npm?

5 ответов


вы можете использовать Sass importer функция для этого. Ср. https://github.com/sass/node-sass#importer--v200.

следующий пример иллюстрирует node-sass@3.0.0 с node@0.12.2:

установите зависимость bower:

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

файл Sass:

@import 'sass-mq/mq';

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

файл визуализации узла:

'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());
});

Это простой и не рекурсивные. The require.resolve функция может помочь справиться с деревом - или подождать, пока npm@3.0.0 чтобы извлечь выгоду из плоского дерева зависимостей.


Если вы ищете удобный ответ в 2017 году и используете Webpack, это было проще всего найти.

предположим, что ваш путь модуля похож на:

node_modules/some-module/sass/app

затем в вашем основном файле scss вы можете использовать:

@import "~some-module/sass/app";

оператор Тильды разрешает любой импорт как модуль.


как сказал дядюшка том,новая версия Sass имеет этот новый importer опции, где каждый "импорт", который вы делаете в своем файле Sass, сначала пройдет через этот метод. Это означает, что вы можете изменить фактический URL-адрес этого метода.

я использовал require.resolve чтобы найти фактический файл ввода модуля.
Взгляните на мою задачу gulp и посмотрите, поможет ли она вам:

'use strict';

var path       = require('path'),
    gulp       = require('gulp'),
    sass       = require('gulp-sass');

var aliases = {};

/**
 * Will look for .scss|sass files inside the node_modules folder
 */
function npmModule(url, file, done) {
  // check if the path was already found and cached
  if(aliases[url]) {
    return done({ file:aliases[url] });
  }

  // look for modules installed through npm
  try {
    var newPath = path.relative('./css', require.resolve(url));
    aliases[url] = newPath; // cache this request
    return done({ file:newPath });
  } catch(e) {
    // if your module could not be found, just return the original url
    aliases[url] = url;
    return done({ file:url });
  }
}

gulp.task("style", function() {
  return gulp.src('./css/app.scss')
    .pipe(sass({ importer:npmModule }))
    .pipe(gulp.dest('./css'));
});

теперь предположим, что вы установили inuit-normalize через узел. Вы можете просто "потребовать" его на ваш файл Sass:

@import "inuit-normalize";

Я надеюсь, что это поможет вам и другим. Потому что добавление относительных путей всегда является болью в заднице:)


вы можете добавить еще includePaths в параметрах рендеринга.

простой пример

фрагмент на основе примера из Oncle Tom.

var options = {
  file: './sample.scss',
  includePaths: [
    path.join(__dirname, 'bower_components'), // bower
    path.join(__dirname, 'node_modules') // npm
  ]
};

sass.render(options, function(err, result){
  console.log(result.css.toString());
});

этого должно хватить. Вы можете включить файлы из пакета, используя @import "my-cool-package/super-grid

пример Webpack и scss-loader

{
  test: /\.scss$/, 
  loader: 'style!css!autoprefixer?browsers=last 2 version!sass?outputStyle=expanded&sourceMap=true&sourceMapContents=true&includePaths[]=./node_modules' 
},

обратите внимание на последний аргумент, includePaths должен быть массив. Поддерживать ум использовать формат


Я sass-npm модуль специально для этого.

npm install sass-npm

в вашем SASS:

// Since node_modules/npm-module-name/style.scss exists, this will be imported.
@import "npm-module-name";

// Since just-a-sass-file isn't an installed npm module, it will be imported as a regular SCSS file.
@import "just-a-sass-file";

Я обычно использую gulp-sass (который имеет тот же параметр "импортер", что и обычный SASS)

var gulp = require('gulp'),
    sass = require('gulp-sass'),
    sassNpm = require('sass-npm')();

затем .pipe(sass()), добавьте импортера в качестве опции:

.pipe(sass({
    paths: ['public/scss'],
    importer: sassNpm.importer,
}))