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

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

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

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

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


person callumacrae    schedule 02.02.2015    source источник
comment
возможный дубликат SASS: импортировать файл из другого каталога?   -  person cimmanon    schedule 10.04.2015
comment
@cimmanon: Что? Нет, это совсем другой вопрос…   -  person callumacrae    schedule 12.04.2015


Ответы (5)


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

Предположим, ваш путь к модулю выглядит так:

node_modules/some-module/sass/app

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

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

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

person ProllyGeek    schedule 03.04.2017
comment
проще всего :) - person Shreyas; 05.04.2017
comment
Мне кажется, это работает автоматически, только если вы используете Webpack. - person CTarczon; 03.05.2017
comment
@CTarczon это следует упомянуть в ответе, многие люди, включая меня, не используют Webpack для компиляции своего Sass. - person ESR; 29.05.2017
comment
Я оказался здесь год спустя, теперь использую Webpack... но почему это решение работает? - person ESR; 11.07.2018
comment
К сведению: если вы используете сборщик посылок вместо веб-пакета, вы можете опустить тильду (~). - person Brian Zelip; 27.03.2019
comment
Спасибо, отлично, теперь, пожалуйста, кто знает, как импортировать SASS из другого домена. Как у вас ---› @import "~some-module/sass/app"; ---› @import "?http://some-site.com/sass/app"; - person Vixson; 20.08.2020

Как упоминал Oncle Tom, новая версия Sass имеет эту новую importer опцию< /a>, где каждый «импорт», который вы делаете в своем файле 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 с помощью node. Вы можете просто «требовать» его в своем файле Sass:

@import "inuit-normalize";

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

person Lucas Motta    schedule 28.04.2015
comment
Это потрясающе! Какое имя файла внутри node_modules/inuit-normalize будет загружено @import "inuit-normalize"? - person mikemaccana; 19.11.2015
comment
относительные пути - это всегда боль в дерзости FTFY :) - person jrharshath; 29.07.2016

Вы можете добавить еще один 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 должен быть массивом. Не забывайте использовать правильный формат.

person Kamil Jopek    schedule 11.09.2015
comment
Это сработало для меня. Вот еще примеры того, как указать параметры sass-loader: github.com/jtangelder/sass -loader#sass-параметры - person Max Mumford; 01.09.2016

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

Следующий пример иллюстрирует [email protected] с [email protected]:

Установите зависимость 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());
});

Это просто и не рекурсивно. Функция require.resolve может помочь справиться с деревом — или подождать, пока [email protected] не воспользуется преимуществами плоского дерева зависимостей.

person Oncle Tom    schedule 10.04.2015
comment
Круто, я не знал о пользовательских функциях импорта в node-sass. Спасибо! - person callumacrae; 12.04.2015
comment
для этого следует использовать includepaths - person n3utrino; 10.11.2016

Специально для этого я создал модуль 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,
}))
person mikemaccana    schedule 20.11.2015
comment
Пожалуйста, заполните поле репозитория в вашем package.json! - person callumacrae; 23.11.2015
comment
Выглядит очень похоже на то, что я написал, за исключением того, что мой получает путь из package.json вместо того, чтобы пытаться требовать styles.scss: gist.github.com/callumacrae/09de2b8294339d6a6785 Вы написали sass-npm-import в своих документах, но, кстати, на самом деле он называется sass-npm. - person callumacrae; 23.11.2015
comment
Добавлено поле репозитория @callumacrae и обновлен README, ура! Если вы хотите добавить получение дерзости от package.json в качестве пиара, сделайте это! - person mikemaccana; 23.11.2015
comment
Ни в одной из вышеперечисленных систем не описывается, как объявить основной файл css пакета. Как (т.е. sass-npm) делает это вывод? - person FreePender; 11.05.2016
comment
@freepender смотрите README. - person mikemaccana; 12.05.2016