Railsで複数のSass(.scssファイル)を使用する際の読み込み方法

## はじめに

RailsでSassを使用し、かつファイルを用途・適応範囲に応じて複数に分割したとき、どのような構成、読み込み方式にするかを実際の失敗談交えながら、記載したいと思います。
最初に「つまづいたこと」で、私が体験した発生した事象や原因などを書いていますが、必要なければ読み飛ばしてもらえればと思います。

### 環境

ruby: 2.6.4
rails: Rails 6.0.3.1  (sass-rails gemを使用)

## まず結論

Railsで複数のSassを使用する際には、読み込みをSprocketsディレクティブ方式(require_tree)ではなく、`@import`で読み込むこと

## つまづいたこと

携わったプロジェクトではSassを使用しており、かつスタイルファイルをメンテしやすくするため、コントローラ単位で.scssファイルを作成していた。
`stylesheets`直下の`application.scss`で全体に共通のスタイルを設定し、`stylesheets/main`配下に複数の.scssファイルを配置。

`application.scss`では、以下の内容を記載していた。
1. ディレクティブ方式でmain配下のscssファイルを読み込み 
2. その後bootstrapなどを読み込み(@import ) 
3. 最後に共通スタイルを設定。

```application.scss
〜 中略 〜
 *= require_tree ./main	
 *= require_self	 *= require_self
 */	 

@import "bootstrap/scss/bootstrap";

〜 中略 〜
// 共通スタイル
body {	
  font-family: ....
}
〜 中略 〜

```

### やろうとしたこと

今回、共通で使用する変数 (ex `$main-color: #3D85C6;`)を作成して、各.scssファイルで使い回そうと思い、以下のように共通変数の定義を追記した。


```application.scss（改修後）
〜 中略 〜
 *= require_tree ./main	
 *= require_self	 *= require_self
 */	 

@import "bootstrap/scss/bootstrap";

〜 中略 〜

// 共通変数
$main-color: #3D85C6;	

// 共通スタイル
body {	
  font-family: ....
}
〜 中略 〜

```

ただ、この状態だとmain配下のscssファイルで変数を使用するとエラーになったため、変数の読み込みが必要だと思い、main配下のscssファイル側で`application.scss`を`@import`した（今思えば、なぜこんな書き方をしたのか、後悔しかない・・・）
結果、main配下のscssファイルでも、変数を使用でき、スタイルも適用されてめでたしめでたしと思っていました。

### その後、起こったこと

カスタマイズを進め、applicaiton.scssに変更を加えていく中で、不可解な現象が、、、

- ブラウザの検証機能でスタイルを見ると、同じスタイルが２つある
- application.scss内のとあるクラスのスタイルから、一部プロパティを削除しても反映されない
（前述のとおり同一スタイルが２つ存在し、片方しかプロパティ削除が反映されていない）

![スクリーンショット 2020-08-17 11.45.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/233987/aa7e1f59-b9ab-7b62-cb07-d7f8118db165.png)

### 原因

すでにお気づきかもしれませんが、「やろうとしたこと」の中で、main配下のscssファイルで、application.scssをimportしてしまったたため、
そこに記載したスタイルが二重で読み込まれてしまいました。なおかつapplication.scssでimportしたbootstrap関連のscssも二重で読み込まれてました。
ただ、applicaiton.scss内のスタイルを変更しても、反映されない原因は結局わからず・・

というわけで、main配下のscssでのimportを削除するとともに、railsで複数のscssファイルを利用するためには、どのような読み込み方法良いのか調べることになりました。。

## railsで複数のscssファイルを利用際の適切な読み込み方法

### 調査した結果

railsguide, rails-sass(gem)のページに記載の通り、**railsで複数のSass(.scssファイル)を使用する際には、Sprocketsディレクティブで読み込まずにSass@importルールを使用する**必要があります。

ディレクティブ方式だと、宣言した変数やmixinが他のscssファイルから利用できない。（まさしく今回私が体験した内容）

- [railsguide]([https://railsguides.jp/asset_pipeline.html#マニフェストファイルとディレクティブ](https://railsguides.jp/asset_pipeline.html#%E3%83%9E%E3%83%8B%E3%83%95%E3%82%A7%E3%82%B9%E3%83%88%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%81%A8%E3%83%87%E3%82%A3%E3%83%AC%E3%82%AF%E3%83%86%E3%82%A3%E3%83%96))より

> Sassファイルを複数使用しているのであれば、Sprocketsディレクティブで読み込まずにSass @importルールを使用する必要があります。このような場合にSprocketsディレクティブを使用してしまうと、Sassファイルが自分自身のスコープに置かれるため、その中で定義されている変数やミックスインが他のSassから利用できなくなってしまいます。

- [sass-railsのReddMe]([https://github.com/rails/sass-rails#important-note](https://github.com/rails/sass-rails#important-note))より

> Important Note
Sprockets provides some directives that are placed inside of comments called require, require_tree, and require_self. DO NOT USE THEM IN YOUR SASS/SCSS FILES. They are very primitive and do not work well with Sass files. Instead, use Sass's native @import directive which sass-rails has customized to integrate with the conventions of your Rails projects.



### 最終的なapplicaiton.scssの記載内容

最終的には以下のような記述内容にしました。
これにより、`common.scss`で定義した変数が他のmain配下のscssファイルでも読み込むことができました。

- `applicaiton.scss`から、`reuire_tree`, `require_self`の記載を削除
- 元々`applicaiton.scss`に記載していた共通スタイルと変数は、`common.scss`を新たに作成して移管
- `@import`でcommon(共通スタイル)、main配下のスタイルを順に読み込み

```application.scss（最終）
〜 中略 〜
 *      
 */

@import "bootstrap/scss/bootstrap";

@import "common";
@import "main/*";

```

## 参考文献

あるべきscssファイルの取り込み方法を理解するために大変参考になりました。

[rails/sass-rails](https://github.com/rails/sass-rails#important-note)

[アセットパイプライン - Railsガイド](https://railsguides.jp/asset_pipeline.html#%E3%83%9E%E3%83%8B%E3%83%95%E3%82%A7%E3%82%B9%E3%83%88%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%81%A8%E3%83%87%E3%82%A3%E3%83%AC%E3%82%AF%E3%83%86%E3%82%A3%E3%83%96)