Korzystając z SASS, jak mogę zaimportować plik z innego katalogu?

93

Czy w SASS można zaimportować plik z innego katalogu? Na przykład, gdybym miał taką strukturę:

- root_directory
    - sub_directory_a
        - _common.scss
        - template.scss
    - sub_directory_b
        - more_styles.scss

template.scss może importować plik _common.scss przy użyciu, @import "common"ale czy plik more_styles.scss może importować plik _common.scss? Próbowałem kilku różnych rzeczy, w tym @import "../sub_directory_a/common"i @import "../sub_directory_a/_common.scss"ale wydaje się, że nic nie działa.

spaaarky21
źródło

Odpowiedzi:

69

Wygląda na to, że pewne zmiany w SASS umożliwiły to, co początkowo próbowałeś:

@import "../subdir/common";

Udało nam się to nawet zadziałać dla jakiegoś zupełnie niepowiązanego folderu znajdującego się w c:\projects\sass:

@import "../../../../../../../../../../projects/sass/common";

Po prostu dodaj wystarczająco dużo, ../aby upewnić się, że skończysz w katalogu głównym dysku i jesteś gotowy do pracy.

Oczywiście to rozwiązanie nie jest ładne, ale nie mogłem uzyskać importu z zupełnie innego folderu do pracy, ani używając I c:\projects\sassani nie ustawiając zmiennej środowiskowej SASS_PATH(z :: load_paths reference ) na tę samą wartość.

Oliver
źródło
9
To jest „dalekie od ładnego”! Ale ta odpowiedź jest bardzo pozytywna. Czy to naprawdę uważane za lepszą praktykę niż -I? Jeśli ta nazwa ścieżki ulegnie zmianie, będzie dużo wyszukiwania i zastępowania; i wymaga takiej samej struktury folderów lokalnych, jak każdy, kto udostępnia plik .scss
WiseOldDuck,
14
„Po prostu dodaj wystarczającą ilość ../, aby mieć pewność, że trafisz do katalogu głównego dysku i gotowe”. Hahaha, to uczyniło mój dzień.
Steve Harrison
4
Radzę całkowicie zignorować tę odpowiedź. Niestety jest to jedno z wielu pytań SO, na które udzielono błędnej odpowiedzi, podając w górę głosów. Jeśli chcesz, aby Twój kod łatwo się zepsuł, użyj go. Jeśli chcesz solidnego rozwiązania, zobacz moją odpowiedź poniżej.
adi518
2
@ adi518: Mógłbym spierać się o twoje stwierdzenie "Jeśli chcesz, aby twój kod łatwo się zepsuł, użyj go." Podane rozwiązanie sprawdza się u nas od tamtego czasu (czyli prawie 4 lata) i niczego nie zepsuło. Wydaje mi się, że jest to jedno z tych rozwiązań, które mogą być nieco brudne, ale wykonują pracę szybko i bez zagłębiania się w wewnętrzne części niektórych narzędzi.
Oliver
2
Poważnie, nie rób tego.
shinzou,
34

Możesz użyć -Iprzełącznika wiersza poleceń lub :load_pathsopcji z kodu Ruby, aby dodać sub_directory_ado ścieżki ładowania Sassa. Więc jeśli używasz Sass z root_directory, zrób coś takiego:

sass -I sub_directory_a --watch sub_directory_b:sub_directory_b

Następnie możesz po prostu użyć @import "common"w more_styles.scss.

Miikka
źródło
1
Świetny. Dokładnie to chciałem wiedzieć. Myślę, że MisterJack też jest na czymś, ale wygląda na to, że Compass ma po prostu folder, który jest już na ścieżce.
spaaarky21
3
Łańcuch -I flag obejmujących więcej niż jeden katalog, np.sass -I sub_directory_a -I sub_directory_c --watch sub_directory_b:sub_directory_b
bob esponja
20

Używając webpacka z sass-loaderem, mogę ~odwołać się do ścieżki głównej projektu. Na przykład zakładając strukturę folderów OP i że jesteś w pliku wewnątrz sub_directory_b:

@import "~sub_directory_a/_common";

Dokumentacja: https://github.com/webpack-contrib/sass-loader#resolving-import-at-rules

Sammi
źródło
8
Wydaje się, że jest to import z, node_modules/a nie z katalogu głównego projektu.
Splaktar
Musiałem dodać "sub_directory_a"do mojego includePathsi używać @import "common";składni podczas korzystania z Angular CLI, który zawiera sass-loader.
Splaktar
To powinna być zatwierdzona odpowiedź.
shinzou,
4
Zgadzam się ze Splaktarem. Z dokumentacji sass-loader: webpack zapewnia zaawansowany mechanizm rozwiązywania plików. Moduł ładujący Sass używa niestandardowej funkcji importera Sassa do przekazywania wszystkich zapytań do mechanizmu rozwiązywania webpacka. W ten sposób możesz importować swoje moduły Sass z node_modules. Wystarczy poprzedzić je ~, aby powiedzieć webpakowi, że nie jest to import względny ... Ważne jest, aby poprzedzać go tylko ~, ponieważ ~ / oznacza katalog domowy.
Anthony
Zauważ, że ~/to nie wydaje mi się odnosić do katalogu domowego. Lub dowolny katalog, który próbowałem przetestować. Czy jest jakiś sposób, aby faktycznie spróbować dowiedzieć się, do czego to się odnosi?
Douglas Gaskell
8

Importowanie .scsspliku z zagnieżdżonym importem o innej pozycji względnej nie będzie działać. najczęściej proponowaną odpowiedzią (używającą dużo ../) jest po prostu brudny hack, który będzie działał tak długo, jak długo dodasz wystarczająco dużo, ../aby dotrzeć do katalogu głównego systemu operacyjnego wdrażania projektu.

  1. Dodaj docelową ścieżkę SCSS jako cel wyszukiwania dla kompilatora SCSS. Można to osiągnąć, dodając folder stylesheets do pliku konfiguracyjnego scss, jest to funkcja używanego frameworka,

używaj :load_pathsw config.rdprzypadku struktur opartych na kompasie (np. szyny)

użyj następującego kodu w scss-config.jsonforfourseven/meteor-scss

{
  "includePaths": [
    "{}/node_modules/ionicons/dist/scss/"
  ]
}
  1. Użyj ścieżek bezwzględnych (zamiast ścieżek względnych).

Na przykład za pomocą programu fourseven/meteor-scssmożesz {}wyróżnić najwyższy poziom swojego projektu, jak na poniższym przykładzie

@import "{}/node_modules/module-name/stylesheet";
helcode
źródło
Nic konkretnego meteor, to był tylko przykład.
helcode
4

Wybrana odpowiedź nie jest realnym rozwiązaniem.

Praktyka OP wydaje się nieregularna. Plik współdzielony / wspólny zwykle partialsznajduje się w standardowym katalogu standardowym. Następnie należy dodać partialskatalog do ścieżek importu konfiguracji, aby rozwiązać częściowe w dowolnym miejscu w kodzie.

Kiedy napotkałem ten problem po raz pierwszy, pomyślałem, że SASS prawdopodobnie daje ci zmienną globalną podobną do zmiennej Node __dirname, która zachowuje bezwzględną ścieżkę do bieżącego katalogu roboczego ( cwd). Niestety tak się nie dzieje, a powodem jest to, że interpolacja @importdyrektywy nie jest możliwa, dlatego nie można wykonać dynamicznej ścieżki importu.

Według docs SASS .

Musisz ustawić :load_pathsw konfiguracji Sassa. Ponieważ OP używa Compass, będę postępować zgodnie z dokumentacją tutaj .

Możesz przejść z rozwiązaniem CLI zgodnie z przeznaczeniem, ale dlaczego? o wiele wygodniej jest go dodać config.rb. Sensowne byłoby użycie CLI do nadpisywania config.rb(np. Różne scenariusze kompilacji).

Zakładając, że config.rbznajdujesz się w katalogu głównym projektu, po prostu dodaj następujący wiersz: add_import_path 'sub_directory_a'

A teraz @import 'common';będzie działać dobrze wszędzie.

Podczas gdy to odpowiada OP, jest więcej.

dodatek

Prawdopodobnie napotkasz przypadki, w których chcesz zaimportować plik CSS w sposób osadzony, to znaczy nie za pomocą @importdyrektywy waniliowej, którą CSS zapewnia po wyjęciu z pudełka, ale rzeczywiste połączenie zawartości pliku CSS z SASS. Jest jeszcze jedno pytanie , na które udzielono odpowiedzi niejednoznacznej (rozwiązanie nie działa w różnych środowiskach). Rozwiązaniem jest więc użycie tego rozszerzenia SASS.

Po zainstalowaniu dodaj następujący wiersz do konfiguracji: require 'sass-css-importer'a następnie gdzieś w kodzie:@import 'CSS:myCssFile';

Zauważ, że rozszerzenie musi zostać pominięte, aby to zadziałało.

Jednak napotkamy ten sam problem podczas próby zaimportowania pliku CSS ze ścieżki innej niż domyślna i add_import_pathnie obsługuje plików CSS. Aby rozwiązać ten problem, musisz dodać kolejną linię w konfiguracji, która jest oczywiście podobna:

add_import_path Sass::CssImporter::Importer.new('sub_directory_a')

Teraz wszystko będzie ładnie działać.

PS, zauważyłem, że sass-css-importerdokumentacja wskazuje, że CSS:oprócz pominięcia .cssrozszerzenia wymagany jest przedrostek . Dowiedziałem się, że to działa niezależnie. Ktoś rozpoczął problem , który do tej pory pozostawał bez odpowiedzi.

adi518
źródło
2

Gulp wykona zadanie oglądania twoich plików sass, a także dodawania ścieżek do innych plików za pomocą includePaths. przykład:

gulp.task('sass', function() {
  return gulp.src('scss/app.scss')
    .pipe($.sass({
      includePaths: sassPaths
    })
    .pipe(gulp.dest('css'));
});
opłata oshry
źródło
7
Rozumiesz, że includePaths po prostu używa -Iopcji z wiersza poleceń, prawda?
cimmanon
2

node-sass(oficjalny wrapper dla SASS node.js) udostępnia opcję wiersza poleceń, --include-pathktóra pomaga w takich wymaganiach.

Przykład:

W package.json:

"scripts": {
    "build-css": "node-sass src/ -o src/ --include-path src/",
}

Teraz, jeśli masz plik src/styles/common.scssw swoim projekcie, możesz go zaimportować w @import 'styles/common';dowolnym miejscu w projekcie.

Więcej informacji można znaleźć pod adresem https://github.com/sass/node-sass#usage-1 .

Vijay Aggarwal
źródło
1

Aby zdefiniować plik do zaimportowania, można użyć wspólnych definicji wszystkich folderów. Musisz tylko mieć świadomość, że jest to zależne od pliku, który go definiujesz. Więcej na temat opcji importu z przykładami możesz sprawdzić tutaj .

Nesha Zoric
źródło
1

Jeśli używasz kompilatora sieci Web w programie Visual Studio, możesz dodać ścieżkę do includePathw pliku compilerconfig.json.defaults. Wtedy nie ma potrzeby ../określania pewnej liczby, ponieważ kompilator użyje funkcji includePath jako lokalizacji do wyszukania importu.

Na przykład:

"includePath": "node_modules/foundation-sites/scss",
DavGarcia
źródło
0

To jest połowa odpowiedzi.

Sprawdź Compass , dzięki któremu możesz umieścić swój folder _common.scssw partialsfolderze, a następnie zaimportować go @import common, ale działa w każdym pliku.

Alessandro Vendruscolo
źródło
Myślę, że odpowiedź Miikki była tym, czego szukałem, ale teraz jestem również ciekawy Compass. Czy katalog podrzędnych jest w jakiś sposób specyficzny dla konkretnego projektu? A może pliki umieszczone w katalogu podszablonów byłyby dostępne „globalnie”, wszędzie tam, gdzie jest używany program Compass?
spaaarky21
4
To wcale nie odpowiada na pytanie.
cimmanon
0

Napotkałem ten sam problem. Z mojego rozwiązania doszedłem do tego. Oto twój kod:

- root_directory
    - sub_directory_a
        - _common.scss
        - template.scss
    - sub_directory_b
        - more_styles.scss

O ile wiem, jeśli chcesz zaimportować jeden plik scss do drugiego, musi to być fragment. Podczas importowania z innego katalogu, nazwij swój plik more_styles.scssdo _more_styles.scss. Następnie zaimportuj go do swojego template.scsspodobnego @import ../sub_directory_b/_more_styles.scss. U mnie to zadziałało. Ale jak wspomniałeś, ../sub_directory_a/_common.scssnie działa. To ten sam katalog template.scss. Dlatego to nie zadziała.

Sajidur Rahman
źródło
0

Zapoznaj się z użyciem parametru includePaths ...

„Kompilator SASS używa każdej ścieżki w loadPaths podczas rozpoznawania SASS @imports”.

https://stackoverflow.com/a/33588202/384884

Deejers
źródło
0

Najlepszym sposobem jest skorzystanie z programu sass-loader. Jest dostępny jako pakiet npm. Rozwiązuje wszystkie problemy związane ze ścieżką i czyni to bardzo łatwym.

Rut Shah
źródło
-6

Miałem ten sam problem i znalazłem rozwiązanie, dodając ścieżkę do pliku:

@import "C: / xampp / htdocs / Scss_addons / Bootstrap / bootstrap";

@import "C: / xampp / htdocs / Scss_addons / Compass / compass";

Netix
źródło
1
Chociaż podobna odpowiedź została udzielona wcześniej, ścieżki bezwzględne są nieco do specyficzne dla serwera jako ogólna odpowiedź (oczywiście powiedziałeś „lubię”).
dakab