syunto07ka / jewelry_box

2 stars 0 forks source link

hoge.module.scss と hoge.scss の使い分けについて #54

Closed piro0919 closed 4 years ago

piro0919 commented 4 years ago

Is your feature request related to a problem? Please describe. hoge.module.scsshoge.scss は、CRA的にどう扱いが異なるか書いてみてください 👍

Describe alternatives you've considered 例えば、mixin用のファイルや定数用のファイルはどこにどういった形で切ると良いでしょうか

Additional context ヒントは、webpackでの処理の違いですね

syunto07ka commented 4 years ago

鍵になるのは以下の部分

modules: {
  getLocalIndent: getCSSModuleLocalIdent,
}

.scssと.module.scssとで設定値が違うのはここ。(他にもあるが、今回はこの部分を見れば良いはず?)

modulesは、CssModulesを使用するかどうかや使用する場合の設定値を設定できるkeyで、defaultはfalseになっている(つまり使わない)

https://webpack.js.org/loaders/css-loader/#modules

そうなったときの.scssと.module.scss の大きな違いは、クラス名が変わること。 .scssファイルにて指定されたクラスはそのまま反映されるが、.module.scssファイルで指定されたクラスは[file]__[localname]_[hash] のように名前が書き換わってしまう。

例えば、mixin用のファイルや定数用のファイルはどこにどういった形で切ると良いでしょうか

この部分の問でいうと、.module.scssでmixinや定数を定義してしまうと、別の名前に書き換わってしまうので.scssに定義しなければいけない(どこに、という問いはできるだけ高級な場所で定義する、でよい?もっと深い答えがある?)

syunto07ka commented 4 years ago

@piro0919 と、ざっくりこんな感じですかね。。?

piro0919 commented 4 years ago

@syunto07ka 着眼点はいい感じです。 👍

.scssと.module.scssとで設定値が違うのはここ。

なぜそう思いましたか?

syunto07ka commented 4 years ago

webpack now 👀

syunto07ka commented 4 years ago

configファイルの中でsassとmodule.sassの設定を行っているのが以下

なぜと言われちゃうと、useで設定している項目が、その部分以外同じだから、という答えになりそうですが。。 sassRegexはsassファイルを識別するための正規表現が代入されてて、excludeの部分はsassModuleだけ省きますよという意味。

webpack.config.js
// Opt-in support for SASS (using .scss or .sass extensions).
            // By default we support SASS Modules with the
            // extensions .module.scss or .module.sass
            {
              test: sassRegex,
              exclude: sassModuleRegex,
              use: getStyleLoaders(
                {
                  importLoaders: 3,
                  sourceMap: isEnvProduction && shouldUseSourceMap,
                },
                'sass-loader'
              ),
              // Don't consider CSS imports dead code even if the
              // containing package claims to have no side effects.
              // Remove this when webpack adds a warning or an error for this.
              // See https://github.com/webpack/webpack/issues/6571
              sideEffects: true,
            },
            // Adds support for CSS Modules, but using SASS
            // using the extension .module.scss or .module.sass
            {
              test: sassModuleRegex,
              use: getStyleLoaders(
                {
                  importLoaders: 3,
                  sourceMap: isEnvProduction && shouldUseSourceMap,
                  modules: {
                    getLocalIdent: getCSSModuleLocalIdent,
                  },
                },
                'sass-loader'
              ),
            },
syunto07ka commented 4 years ago

@piro0919

piro0919 commented 4 years ago

@syunto07ka

なぜと言われちゃうと、useで設定している項目が、その部分以外同じだから、という答えになりそうですが。。 sassRegexはsassファイルを識別するための正規表現が代入されてて、excludeの部分はsassModuleだけ省きますよという意味。

正解です 👍

では、以下のコミットはどこが良くないかわかりますか? https://github.com/syunto07ka/jewelry_box/commit/7de1b37dcc6b77746b0d16ce5ccb9df7bd8e192b

syunto07ka commented 4 years ago

クラス名の付け方が異なるので、このコミット 7de1b37 だと.module.scssを読み込んだときにスタイル情報が当たらない。のでどちらにもLocalIdentNameの指定をして上げる必要がある。もっというとcssを使う場合も考慮して、css側の設定も変更したほうがよい

ですかね? @piro0919

{
              test: cssRegex,
              exclude: cssModuleRegex,
              use: getStyleLoaders({
                importLoaders: 1,
                sourceMap: isEnvProduction && shouldUseSourceMap,
              }),
              // Don't consider CSS imports dead code even if the
              // containing package claims to have no side effects.
              // Remove this when webpack adds a warning or an error for this.
              // See https://github.com/webpack/webpack/issues/6571
              sideEffects: true,
            },
            // Adds support for CSS Modules (https://github.com/css-modules/css-modules)
            // using the extension .module.css
            {
              test: cssModuleRegex,
              use: getStyleLoaders({
                importLoaders: 1,
                sourceMap: isEnvProduction && shouldUseSourceMap,
                modules: {
                  getLocalIdent: getCSSModuleLocalIdent,
                },
              }),
            },
piro0919 commented 4 years ago

@syunto07ka

クラス名の付け方が異なるので、このコミット 7de1b37 だと.module.scssを読み込んだときにスタイル情報が当たらない。のでどちらにもLocalIdentNameの指定をして上げる必要がある。もっというとcssを使う場合も考慮して、css側の設定も変更したほうがよい

ちょっと表現が曖昧過ぎてよくわからないです。

CRAのwebpackでは、以下の4つの設定がcssファイルやscssファイルに関する設定となっています。

            {
              test: cssRegex,
              exclude: cssModuleRegex,
              use: getStyleLoaders({
                importLoaders: 1,
                sourceMap: isEnvProduction && shouldUseSourceMap,
              }),
              sideEffects: true,
            },
            {
              test: cssModuleRegex,
              use: getStyleLoaders({
                importLoaders: 1,
                sourceMap: isEnvProduction && shouldUseSourceMap,
                modules: {
                  getLocalIdent: getCSSModuleLocalIdent,
                },
              }),
            },
            {
              test: sassRegex,
              exclude: sassModuleRegex,
              use: getStyleLoaders(
                {
                  importLoaders: 3,
                  sourceMap: isEnvProduction && shouldUseSourceMap,
                },
                'sass-loader'
              ),
              sideEffects: true,
            },
            {
              test: sassModuleRegex,
              use: getStyleLoaders(
                {
                  importLoaders: 3,
                  sourceMap: isEnvProduction && shouldUseSourceMap,
                  modules: {
                    getLocalIdent: getCSSModuleLocalIdent,
                  },
                },
                'sass-loader'
              ),
            },

正規表現を見て頂けるとわかると思いますが、上から順に以下のファイルに対する設定となります。

  1. css modulesをかまさないcssに対する設定(hoge.cssなど)
  2. css modulesをかませるcssに対する設定(hoge.modele.cssなど)
  3. css modulesをかまさないsassに対する設定(hoge.scssなど)
  4. css modulesをかませるsassに対する設定(hoge.modele.scssなど)

今回はscssファイルに限った話をしているので、そもそも対象となる設定は3.と4.に限られます。 3.と4.の設定の違いはmodulesというオプションをgetStyleLoaders関数に渡しているか否かの違いのみとなっています。

そもそもmodulesとは一体なんぞやという話になるのですが。

css-loaderの公式を見て頂けるとわかると思うのですが、modulesオプションを追加すると、対象となるファイルはcss modules用のファイルとして扱われるようになります。 その結果、hoge.module.scssファイルを切ってやると、クラス名が勝手に変換され、カプセル化が行われるという仕組みになっているわけです。

そこで、babel-plugin-react-css-modulesとの兼ね合いの話になってくるのですが。

これ自身の説明は以前したはずなのでざっくりと書いてしまいますが、素のcss modulesを使ってしまった場合、割り当てるclassNameの変数名がlinterや規約的に良くなかったり、ロジック側かスタイル側で使用されているのかなどがわかりづらいなどの問題が発生してしまいます。 それを解決してくれるのがこのパッケージで、カプセル化を行いたいスタイリングについてはstyleNameというpropsを渡せば、このパッケージが良しなにやってくれるわけですね。

ここで1つ誤解されているかもしれないのですが。

babel-plugin-react-css-modulesの対象となるファイルは、当たり前ですがcss modulesを当ててやりたいファイルになるため、上記の設定のうち2.及び4.が対象となります。 そのため、1.や3.の設定を触ることは絶対になく、ましてやcss及びsassの全体の設定を触るようなことをしてはいけません。 🙅‍♂️

babel-plugin-react-css-modulesの導入については、babelの設定をいじってやればほぼ解決するのですが。 ここで1つ問題となるのが、素のcss modulesと素のbabel-plugin-react-css-modulesでは、クラス名の変換のロジックが以下のように異なるのです。

css modules: [name]__[local]___[hash:base64:5] babel-plugin-react-css-modules: [path]___[name]__[local]___[hash:base64:5]

そのため、css及びsass側のクラス名の変換に関する設定を修正してやらないといけない、ということになります。 今回のケースでは、scssファイルのみを対象としているため、上記の設定のうち4.の設定を触ってあげれば良いと思います。

修正方法についてはすでに把握されていると思いますが、大体こんな感じになると思います。

syunto07ka commented 4 years ago

babel-plugin-react-css-modulesの対象となるファイルは、当たり前ですがcss modulesを当ててやりたいファイルになるため、上記の設定のうち2.及び4.が対象となります。 そのため、1.や3.の設定を触ることは絶対になく、ましてやcss及びsassの全体の設定を触るようなことをしてはいけません。 🙅‍♂️

まさに誤解してました。。 やっと理解しましたー!babel-pluginのパッケージよく見れてないな。。もう一回読みますー