scssをwebpack4でトランスパイル

CSSのメタ言語であるscssを、
node.js環境でcssにトランスパイルする方法を記載します。


CSSと比較してscssは下記利点があります。

- 変数が使える
- ネストが使える
- 名前空間でネストが可能
- 別のファイルを読み込んで使える
- スタイルの使いまわしができる(主にmixinとか)
- 四則演算が普通にできる(calcとか使わなくていい)
- 関数が使える(輝度変えたりとか)
- 制御文が使える(@ifとか@forとか)

lessとかsass記法とかあるようですが、
cssの記法がそのまま使えるscss記法が、
個人的に楽なので使います。

前置きが少し長くなりましたが、始めます。

## 環境
node.js v8.12.0
npm v6.4.1
webpack 4.29.6

OSとかは何でもいいのですが、
今回はwindows10でVSCodeを使って作っていきます。
ターミナルはgitbashを入れています。
※特に環境は選ばないので、コマンドプロンプトとかでOK

## パッケージの作成
任意のディレクトリで初期化します。

```console
$ npm -y init
```

-yをつけなければ項目を設定できますが、
今回は目的から外れるので割愛します。
package.jsonが作成されます。

## トランスパイルに必要なモジュールをインストールする
```console
$ npm -D install webpack webpack-cli
$ npm -D install sass-loader node-sass style-loader css-loader
$ npm -D install mini-css-extract-plugin optimize-css-assets-webpack-plugin
```
-Dは開発用モジュールとして保存されるオプションで、
付けなくてもよいですが、用途的には開発用なので、
付けました。

webpackのloaderとは、指定のファイルをバンドルするものです
「バンドルする」とは1つにまとめる意味です。

| npm              |  用途 　| 
|:--|:--|
|webpack           |ファイルを1つまとめたり、別言語に変換したりする。|
|webpack-cli       |webpackをコマンドラインから実行する為に必要。今回は必須。|
|sass-loader       |(scss)sassをバンドルする。|
|node-sass         |sass-loaderが依存しているので必要。|
|style-loader      |<link>タグにcssを展開する機能。|
|css-loader        |cssをjavascriptに埋め込む。|
|mini-css-extract-plugin|cssを外部ファイルに出力|
|optimize-css-assets-webpack-plugin|cssを圧縮する|


##Webpackの設定ファイルを作る
webpack.config.jsファイルを作成し、に次の設定を

```js:webpack.config.js
const path = require('path');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');

module.exports = {
  entry: {
    anyname: './src/scss/style.scss',
  },
  output: {
    // 全体の設定
    path: path.resolve(__dirname, 'dest'),
  },
  module: {
    rules: [
      {
        test: /\.scss$/,
        use: [
          { loader: MiniCssExtractPlugin.loader },
          { loader: 'css-loader' },
          { loader: 'sass-loader' },
        ],
      }
    ],
  },
  plugins:[
    // cssの出力先を指定する
    new MiniCssExtractPlugin({ filename: 'style/[name].css' }),
  ],
  optimization: {
    minimizer: [new OptimizeCSSAssetsPlugin({})],
  },
}
```

## トランスパイルするscssファイルを作成する

```scss:./src/scss/style.scss
body {
  background-color: aqua;
}
```

##実行前にフォルダ構成を確認

![image.png](https://qiita-image-store.s3.amazonaws.com/0/380290/217392a5-ae6b-40ad-2d3c-8923c4c6771f.png)

実際に作ったのは、
style.scssとwebpack.config.jsのみです。

##実行してcssを出力

```console
$ npx webpack --mode production
```
--mode指定はwebpack4から必須です。
developmentを指定すると、cssの中身が圧縮されません。

dest/style/にanyname.cssが出力されるので中身を確認します。

```css:./dest/style/anyname.css
body{background-color:#0ff}
```

まあほぼそのままなので分かりにくいですが、
一応ちゃんと圧縮されて出力されました。


## 副作用的に得えられた知識
- entry:を増やせば、バンドルするjsファイルを分けられる
  - あまりにもファイルサイズが大きくなるなら分けるべきだろう

## 残った課題
- 不要な〇〇.jsが出力されてしまう
  - webpack自体がjavascriptをバンドルする用途の為、仕方ない？？
  - scssからcssだけが目的なら、素直にRubyでトランスパイルすればいい気がした
- 今回はscssから外部ファイル読み込みに対応してない
  - url-loaderやfile-loaderを追加すればOK

## 感想
公式ドキュメントだけは分からない部分が多いので、
個人が調べたり、実際ソースみないといけないパターンが多かったです。
その為、調べたことはどこかに残しておけば財産になりそうです。

## 参考にさせて頂いたサイト
[webpack公式](https://webpack.js.org/)
[Loading Fonts with webpack](https://chriscourses.com/blog/loading-fonts-webpack)
[CSSのメタ言語Sass(SCSS)、LESSの完全入門](https://qiita.com/ritukiii/items/67b3c50002b48c6186d6)
[最新版で学ぶwebpack 4入門 – スタイルシート(CSSやSass)を取り込む方法](https://ics.media/entry/17376)
[WebPack + Sass + file-loader のサンプル](https://github.com/ics-creative/170330_webpack/tree/master/tutorial-sass-image-file)
[Sassで色を調整する](https://qiita.com/hrdaya/items/9f1692ba5b879f48823d)
[webpack@4 でCSSを抽出する際は mini-css-extract-plugin を使う](https://numb86-tech.hatenablog.com/entry/2018/10/24/221130)
[Webpack4でes6/sassをcompile](https://qiita.com/macotok/items/c4df30baf29ee4b9bc5e)