shakapackerでcssからsassに移行した際にコンパイルに失敗する

## やろうとしていたこと。
Rails７にReactを導入しようとしてまして、その際、shakapackerを用いつつ、sassでスタイルシートを管理するためにセッティングしている最中でした。
.sassにしても.scssにしてもcssに変換がうまくいかず困ってしまったので、備忘録して記載します。


## どんなエラーが出ていたか。
以下のように、`bin/shakapacker-dev-server`を実行後、style-loaderと、sass-loaderのインポート時にエラーが出ていました。
ログ後半では、sass-loaderも利用しているような雰囲気があって、エラーも`Error: expected "{".`と表示されているなど、名前を変更したapplicatio.sassの中身が悪いのかなと書き方をいろいろ試しているうちに時間を使ってしまいました。

```bash
app-1      | ERROR in ./app/javascript/packs/application.scss (./app/javascript/packs/application.scss.webpack[javascript/auto]!=!./node_modules/css-loader/dist/cjs.js??ruleSet[1].rules[3].use[1]!./node_modules/postcss-loader/dist/cjs.js??ruleSet[1].rules[3].use[2]!./node_modules/sass-loader/dist/cjs.js??ruleSet[1].rules[3].use[3]!./node_modules/sass-loader/dist/cjs.js!./node_modules/style-loader/dist/cjs.js!./node_modules/css-loader/dist/cjs.js!./app/javascript/packs/application.scss)
app-1      | Module build failed (from ./node_modules/sass-loader/dist/cjs.js):
app-1      | Error: expected "{".
app-1      |   ╷
app-1      | 2 │       import API from "!../../../node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js";
app-1      |   │                                                                                                     ^
app-1      |   ╵
app-1      |   /myapp/app/javascript/packs/application.scss 2:101  root stylesheet
app-1      |  @ ./app/javascript/packs/application.scss
app-1      | 
app-1      | ERROR in ./app/javascript/packs/application.scss
app-1      | Module build failed (from ./node_modules/mini-css-extract-plugin/dist/loader.js):
app-1      | HookWebpackError: Module build failed (from ./node_modules/sass-loader/dist/cjs.js):
app-1      | Error: expected "{".
app-1      |   ╷
app-1      | 2 │       import API from "!../../../node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js";
app-1      |   │                                                                                                     ^
app-1      |   ╵
app-1      |   /myapp/app/javascript/packs/application.scss 2:101  root stylesheet
app-1      |     at tryRunOrWebpackError (/myapp/node_modules/webpack/lib/HookWebpackError.js:88:9)
app-1      |     at __webpack_require_module__ (/myapp/node_modules/webpack/lib/Compilation.js:5246:12)
app-1      |     at __webpack_require__ (/myapp/node_modules/webpack/lib/Compilation.js:5203:18)
app-1      |     at /myapp/node_modules/webpack/lib/Compilation.js:5275:20
app-1      |     at symbolIterator (/myapp/node_modules/neo-async/async.js:3485:9)
app-1      |     at done (/myapp/node_modules/neo-async/async.js:3527:9)
app-1      |     at Hook.eval [as callAsync] (eval at create (/myapp/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:15:1)
app-1      |     at Hook.CALL_ASYNC_DELEGATE [as _callAsync] (/myapp/node_modules/tapable/lib/Hook.js:18:14)
app-1      |     at /myapp/node_modules/webpack/lib/Compilation.js:5181:43
app-1      |     at symbolIterator (/myapp/node_modules/neo-async/async.js:3482:9)
app-1      |     at timesSync (/myapp/node_modules/neo-async/async.js:2297:7)
app-1      |     at Object.eachLimit (/myapp/node_modules/neo-async/async.js:3463:5)
app-1      |     at /myapp/node_modules/webpack/lib/Compilation.js:5143:16
app-1      |     at symbolIterator (/myapp/node_modules/neo-async/async.js:3485:9)
app-1      |     at timesSync (/myapp/node_modules/neo-async/async.js:2297:7)
app-1      |     at Object.eachLimit (/myapp/node_modules/neo-async/async.js:3463:5)
app-1      |     at /myapp/node_modules/webpack/lib/Compilation.js:5111:15
app-1      |     at symbolIterator (/myapp/node_modules/neo-async/async.js:3485:9)
app-1      |     at done (/myapp/node_modules/neo-async/async.js:3527:9)
app-1      |     at /myapp/node_modules/webpack/lib/Compilation.js:5057:8
app-1      |     at /myapp/node_modules/webpack/lib/Compilation.js:3495:6
app-1      |     at /myapp/node_modules/webpack/lib/HookWebpackError.js:68:3
app-1      |     at Hook.eval [as callAsync] (eval at create (/myapp/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:15:1)
app-1      |     at Cache.store (/myapp/node_modules/webpack/lib/Cache.js:113:20)
app-1      |     at ItemCacheFacade.store (/myapp/node_modules/webpack/lib/CacheFacade.js:141:15)
app-1      |     at /myapp/node_modules/webpack/lib/Compilation.js:3494:11
app-1      |     at /myapp/node_modules/webpack/lib/Cache.js:97:34
app-1      |     at Array.<anonymous> (/myapp/node_modules/webpack/lib/cache/MemoryCachePlugin.js:45:13)
app-1      |     at /myapp/node_modules/webpack/lib/Cache.js:97:19
app-1      |     at Hook.eval [as callAsync] (eval at create (/myapp/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:19:1)
app-1      |     at Cache.get (/myapp/node_modules/webpack/lib/Cache.js:81:18)
app-1      |     at ItemCacheFacade.get (/myapp/node_modules/webpack/lib/CacheFacade.js:115:15)
app-1      |     at Compilation._codeGenerationModule (/myapp/node_modules/webpack/lib/Compilation.js:3462:9)
app-1      |     at codeGen (/myapp/node_modules/webpack/lib/Compilation.js:5045:11)
app-1      |     at symbolIterator (/myapp/node_modules/neo-async/async.js:3482:9)
app-1      |     at timesSync (/myapp/node_modules/neo-async/async.js:2297:7)
app-1      |     at Object.eachLimit (/myapp/node_modules/neo-async/async.js:3463:5)
app-1      |     at /myapp/node_modules/webpack/lib/Compilation.js:5075:14
app-1      |     at processQueue (/myapp/node_modules/webpack/lib/util/processAsyncTree.js:61:4)
app-1      |     at process.processTicksAndRejections (node:internal/process/task_queues:77:11)
app-1      | -- inner error --
app-1      | Error: Module build failed (from ./node_modules/sass-loader/dist/cjs.js):
app-1      | Error: expected "{".
app-1      |   ╷
app-1      | 2 │       import API from "!../../../node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js";
app-1      |   │                                                                                                     ^
app-1      |   ╵
app-1      |   /myapp/app/javascript/packs/application.scss 2:101  root stylesheet
app-1      |     at Object.<anonymous> (/myapp/node_modules/css-loader/dist/cjs.js??ruleSet[1].rules[3].use[1]!/myapp/node_modules/postcss-loader/dist/cjs.js??ruleSet[1].rules[3].use[2]!/myapp/node_modules/sass-loader/dist/cjs.js??ruleSet[1].rules[3].use[3]!/myapp/node_modules/sass-loader/dist/cjs.js!/myapp/node_modules/style-loader/dist/cjs.js!/myapp/node_modules/css-loader/dist/cjs.js!/myapp/app/javascript/packs/application.scss:1:7)
app-1      |     at /myapp/node_modules/webpack/lib/javascript/JavascriptModulesPlugin.js:457:10
app-1      |     at Hook.eval [as call] (eval at create (/myapp/node_modules/tapable/lib/HookCodeFactory.js:19:10), <anonymous>:7:1)
app-1      |     at Hook.CALL_DELEGATE [as _call] (/myapp/node_modules/tapable/lib/Hook.js:14:14)
app-1      |     at /myapp/node_modules/webpack/lib/Compilation.js:5248:39
app-1      |     at tryRunOrWebpackError (/myapp/node_modules/webpack/lib/HookWebpackError.js:83:7)
app-1      |     at __webpack_require_module__ (/myapp/node_modules/webpack/lib/Compilation.js:5246:12)
app-1      |     at __webpack_require__ (/myapp/node_modules/webpack/lib/Compilation.js:5203:18)
app-1      |     at /myapp/node_modules/webpack/lib/Compilation.js:5275:20
app-1      |     at symbolIterator (/myapp/node_modules/neo-async/async.js:3485:9)
app-1      |     at done (/myapp/node_modules/neo-async/async.js:3527:9)
app-1      |     at Hook.eval [as callAsync] (eval at create (/myapp/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:15:1)
app-1      |     at Hook.CALL_ASYNC_DELEGATE [as _callAsync] (/myapp/node_modules/tapable/lib/Hook.js:18:14)
app-1      |     at /myapp/node_modules/webpack/lib/Compilation.js:5181:43
app-1      |     at symbolIterator (/myapp/node_modules/neo-async/async.js:3482:9)
app-1      |     at timesSync (/myapp/node_modules/neo-async/async.js:2297:7)
app-1      |     at Object.eachLimit (/myapp/node_modules/neo-async/async.js:3463:5)
app-1      |     at /myapp/node_modules/webpack/lib/Compilation.js:5143:16
app-1      |     at symbolIterator (/myapp/node_modules/neo-async/async.js:3485:9)
app-1      |     at timesSync (/myapp/node_modules/neo-async/async.js:2297:7)
app-1      |     at Object.eachLimit (/myapp/node_modules/neo-async/async.js:3463:5)
app-1      |     at /myapp/node_modules/webpack/lib/Compilation.js:5111:15
app-1      |     at symbolIterator (/myapp/node_modules/neo-async/async.js:3485:9)
app-1      |     at done (/myapp/node_modules/neo-async/async.js:3527:9)
app-1      |     at /myapp/node_modules/webpack/lib/Compilation.js:5057:8
app-1      |     at /myapp/node_modules/webpack/lib/Compilation.js:3495:6
app-1      |     at /myapp/node_modules/webpack/lib/HookWebpackError.js:68:3
app-1      |     at Hook.eval [as callAsync] (eval at create (/myapp/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:15:1)
app-1      |     at Cache.store (/myapp/node_modules/webpack/lib/Cache.js:113:20)
app-1      |     at ItemCacheFacade.store (/myapp/node_modules/webpack/lib/CacheFacade.js:141:15)
app-1      |     at /myapp/node_modules/webpack/lib/Compilation.js:3494:11
app-1      |     at /myapp/node_modules/webpack/lib/Cache.js:97:34
app-1      |     at Array.<anonymous> (/myapp/node_modules/webpack/lib/cache/MemoryCachePlugin.js:45:13)
app-1      |     at /myapp/node_modules/webpack/lib/Cache.js:97:19
app-1      |     at Hook.eval [as callAsync] (eval at create (/myapp/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:19:1)
app-1      |     at Cache.get (/myapp/node_modules/webpack/lib/Cache.js:81:18)
app-1      |     at ItemCacheFacade.get (/myapp/node_modules/webpack/lib/CacheFacade.js:115:15)
app-1      |     at Compilation._codeGenerationModule (/myapp/node_modules/webpack/lib/Compilation.js:3462:9)
app-1      |     at codeGen (/myapp/node_modules/webpack/lib/Compilation.js:5045:11)
app-1      |     at symbolIterator (/myapp/node_modules/neo-async/async.js:3482:9)
app-1      |     at timesSync (/myapp/node_modules/neo-async/async.js:2297:7)
app-1      |     at Object.eachLimit (/myapp/node_modules/neo-async/async.js:3463:5)
app-1      |     at /myapp/node_modules/webpack/lib/Compilation.js:5075:14
app-1      |     at processQueue (/myapp/node_modules/webpack/lib/util/processAsyncTree.js:61:4)
app-1      |     at process.processTicksAndRejections (node:internal/process/task_queues:77:11)
app-1      | 
app-1      | Generated code for /myapp/node_modules/css-loader/dist/cjs.js??ruleSet[1].rules[3].use[1]!/myapp/node_modules/postcss-loader/dist/cjs.js??ruleSet[1].rules[3].use[2]!/myapp/node_modules/sass-loader/dist/cjs.js??ruleSet[1].rules[3].use[3]!/myapp/node_modules/sass-loader/dist/cjs.js!/myapp/node_modules/style-loader/dist/cjs.js!/myapp/node_modules/css-loader/dist/cjs.js!/myapp/app/javascript/packs/application.scss
app-1      | 1 | throw new Error("Module build failed (from ./node_modules/sass-loader/dist/cjs.js):\nError: expected \"{\".\n\u001b[34m  ╷\u001b[0m\n\u001b[34m2 │\u001b[0m       import API from \"!../../../node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js\"\u001b[31m\u001b[0m;\n\u001b[34m  │\u001b[0m \u001b[31m                                                                                                    ^\u001b[0m\n\u001b[34m  ╵\u001b[0m\n  /myapp/app/javascript/packs/application.scss 2:101  root stylesheet");
app-1      | 
app-1      | webpack 5.93.0 compiled with 2 errors in 1828 ms
```

## 解決方法
webpack.config.jsに書いたカスタムコンフィグの"style-loader","css-loader"を削除して、sass-loaderだけセットしたらコンパイルができました。
参考にしたのは以下の記事です。
端的に説明すると他のローダーに既に含まれているローダーを重複して利用するとエラーになることがあるということでした。

https://stackoverflow.com/questions/70708993/error-importing-css-modules-with-storybook-webpack-5

中身まで見に行ってどこで重複しているのかまでは調査できていないので、もし、この記事見て特定した方いらっしゃいましたら教えてくださると助かります。


## 変更前のwebpack.config.js
```js
// See the shakacode/shakapacker README and docs directory for advice on customizing your webpackConfig.
// config/webpack/webpack.config.js
const {generateWebpackConfig} = require('shakapacker');
const merge = require("webpack-merge");

const customConfig = {
    resolve: {
        extensions: ['.scss','.css', '.sass'],
    },
    module: {
        rules: [
            {
                test: /\.s[ac]ss$/i,
                use: [
                    // Compiles Sass to CSS
                    "sass-loader",
                    // Creates `style` nodes from JS strings
                    "style-loader",
                    // Translates CSS into CommonJS
                    "css-loader",

                ],
            },
        ],
    },
};

module.exports = generateWebpackConfig(customConfig);
```

## 変更後のwebpack.config.js
```js
// See the shakacode/shakapacker README and docs directory for advice on customizing your webpackConfig.
// config/webpack/webpack.config.js
const {generateWebpackConfig} = require('shakapacker');
const merge = require("webpack-merge");

const customConfig = {
    resolve: {
        extensions: ['.scss','.css', '.sass'],
    },
    module: {
        rules: [
            {
                test: /\.s[ac]ss$/i,
                use: [
                    // Compiles Sass to CSS
                    "sass-loader", // ←他のloaderを消しただけ。
                ],
            },
        ],
    },
};

module.exports = generateWebpackConfig(customConfig);
```