Pytanie Importowanie Sassa przez npm


Obecnie w naszych plikach Sass mamy coś takiego:

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

To jest złe, ponieważ nie jesteśmy pewni ścieżki: może być ../node_modules, mogłoby być ../../../../../node_modules, z powodu tego, jak npm instaluje rzeczy.

Czy istnieje sposób w Sass, który możemy przeszukać, dopóki nie znajdziemy node_modules? A może nawet właściwy sposób włączenia Sassa przez npm?


29
2018-02-02 17:48


pochodzenie


możliwy duplikat SASS: importować plik z innego katalogu? - cimmanon
@imimmanon: Co? Nie, to zupełnie inne pytanie ... - callumacrae


Odpowiedzi:


Możesz użyć Sassa importer funkcja do tego. Cf. https://github.com/sass/node-sass#importer--v200.

Poniższy przykład ilustruje node-asass@3.0.0 z node@0.12.2:

Zainstaluj zależność bower:

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

Plik Sass:

@import 'sass-mq/mq';

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

Plik renderowania węzła:

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

Ten jest prosty i nie rekurencyjny. The require.resolve funkcja może pomóc w uporaniu się z drzewem - lub poczekać, aż npm@3.0.0 skorzysta z drzewa zależności płaskich.


8
2018-04-10 17:12



Wspaniale, nie wiedziałem o niestandardowych funkcjach importera w węźle sass. Dzięki! - callumacrae
do tego należy użyć includeepaths - n3utrino


Jeśli szukasz wygodnej odpowiedzi w 2017 roku i korzystasz z Webpacka, to było to najłatwiejsze, jakie znalazłem.

Załóżmy, że twoja ścieżka modułu wygląda następująco:

node_modules/some-module/sass/app

Następnie w głównym pliku scss możesz użyć:

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

Operator tyldy rozpatruje każdy import jako moduł.


33
2018-04-03 10:50



najprostszy ze wszystkich :) - Shreyas
Wydaje mi się, że to działa automatycznie tylko wtedy, gdy używasz Webpacka. - CTarczon
@CTarczon powinno to być wspomniane w odpowiedzi, wielu ludzi, łącznie z mną, nie używam Webpacka do kompilacji swojego Sassa. - Edmund Reed
Znajduję się tutaj rok później, teraz używając Webpacka ... ale dlaczego to rozwiązanie działa? - Edmund Reed


Jak wspomniał Oncle Tom, the nowa wersja Sass ma to nowe importer opcja, gdzie każdy "import", który zrobisz na swoim pliku Sass, przejdzie najpierw przez tę metodę. Oznacza to, że możesz następnie zmodyfikować faktyczny adres URL tej metody.

Użyłem require.resolve zlokalizować rzeczywisty plik wpisu modułu.
Rzuć okiem na moje zadanie i sprawdź, czy to ci pomoże:

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

Teraz powiedzmy, że zainstalowałeś inuit-normalize za pomocą węzła. Możesz po prostu "wymagać" tego na swoim pliku Sass:

@import "inuit-normalize";

Mam nadzieję, że to pomoże Tobie i innym. Ponieważ dodawanie ścieżek względnych zawsze jest bolesne w dupie :)


16
2018-04-28 16:03



To cudownie! Jaka jest nazwa pliku wewnątrz node_modules/inuit-normalize by @import "inuit-normalize"obciążenie? - mikemaccana
"względne ścieżki to zawsze ból w sassie" FTFY :) - jrharshath


Możesz dodać kolejne includePaths do twoich opcji renderowania.

Prosty przykład

Snippet na podstawie przykładu z 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());
});

To powinno wystarczyć. Możesz dołączyć pliki z pakietu za pomocą @import "my-cool-package/super-grid

Przykład pakietu Webpack i scss-loader

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

Zwróć uwagę na ostatni argument, includePaths musi być tablicą. Pamiętaj, aby użyć odpowiedni format


14
2017-09-11 09:29



To działało dla mnie. Oto więcej przykładów, jak określić opcje sass-loader: github.com/jtangelder/sass-loader#sass-options - Max Mumford
Znacznie czystsze niż cokolwiek innego IMHO, dzięki! - Mike Gleason jr Couturier


Zrobiłem sass-npm moduł specjalnie do tego.

npm install sass-npm

W twoim 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";

Zwykle używam gulp-sass (który ma tę samą opcję "importera" co zwykły SASS)

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

Następnie w swoim .pipe(sass()), dodaj importera jako opcję:

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

3
2017-11-20 12:30



Proszę wypełnić pole repozytorium w pliku package.json! - callumacrae
Wygląda całkiem podobnie do tego, który napisałem, z wyjątkiem tego, że moja ścieżka pochodzi z pliku package.json, zamiast próbować wymagać styles.scss: gist.github.com/callumacrae/09de2b8294339d6a6785  Napisałeś "sass-npm-import" w swoich dokumentach, ale tak na marginesie nazywa się to "sass-npm". - callumacrae
Dodano pole repozytorium @callumacrae i zaktualizowano README, okrzyki! Jeśli chcesz dodać pobieranie sassa package.json jako PR na to! - mikemaccana
Żaden z powyższych systemów nie opisuje, jak zadeklarować, co jest "głównym" plikiem css pakietu. W jaki sposób (tj. sass-npm) wywnioskować to? - FreePender
@freepender zobacz README. - mikemaccana