webpack入門して仲良くなりたい～Loader編～

#仲良くなりたい

- [基本編](https://qiita.com/gabochi/items/b0bc1d522b12fe124f90)
- [開発環境編](https://qiita.com/gabochi/items/caca7cdfaa4a35b73246)
- Loader編　←今ココ!!
- Plugin編　近日公開予定

基本的なバンドルの方法と開発がラクになるように設定を行ったので、次はLoadersと仲良くなりたいと思います。
webpackの神髄はloaderらしいです

# Loaderってなに？

Loaderは、jsファイル以外のものをバンドルするための機能です。
役目はjsファイルとして読み取れる形に変換すること

ここでは、cssファイル・画像ファイルとTypeScriptのコンパイルついて扱います。

# cssファイルをバンドルする

cssファイルをバンドルするには2つのloaderを使います。

- css-loader
 - cssファイルの読み込み　　
- style-loader
 - 読み込んだcssファイルをstyleとして反映させる
 
# css-loaderとstyle-loader

まずは`css-loader`と`style-loader`をインストールして`webpack.config.js`の設定を追加します。

```
npm install css-loader@3.4.2 style-loader@1.1.3 -D
```

```webpack.config.js
// loaderの設定
module.exports = {
//　　　.
//　　　.
//　　　.
  rules: [
    {
      // 適用するファイルの拡張子を正規表現で記述
      test: /\.css$/,
      // 使用するloaderを指定
      use: ["style-loader", "css-loader"]
    }
  ]
}
```

- rules
 - 今後、loaderの設定をするときはこのrules配列の中で行う
- test
 - ここでは、loaderを適用するファイルの拡張子を正規表現で記述
- use
 - 使うloaderを記述。loaderは実行される順番が大切です。cssファイルが変換していないのにstyleに適用することはできません。実行順番は後ろからです。注意します。

次にcssファイルを用意します。

```src/css/style.css
.back {
  background-color: #d2d2d2;
}
```

`app.js`をわかりやすくします

```src/js/app.js
import "../css/style.css";

document.body.classList.add("back");
```

これで準備完了！
実行して画面を確認してみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/251047/407afd8e-b428-e799-642e-bbf7b641173a.png)

背景が灰色になりました。さらに、開発者ツールを確認すると`<style>`タグにスタイルが反映されています。


# 画像ファイルをバンドルする

## url-loader
次は画像ファイルをバンドルします。
そのために必要なloaderは`url-loader`です

```
npm install url-loader@3.0.0 -D
```

次に`webpack.config.js`の設定を加えます。loaderの設定なのでrules配列の中に記述します。

```webpack.config.js
 {
     test: /\.(png|jpg|gif)$/,
     loader: "url-loader"
 }
```

設定を書いたら、自分の好きなところに画像ファイルを入れて`app.js`を書き換えます

```app.js
import "../css/style.css";
import backImage from "../images/back-image.jpg";

document.body.classList.add("back");

const image = new Image();
image.src = backImage;
document.body.appendChild(image);
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/251047/330bdfd2-ba4b-58d9-fcce-2a19efaa2ec1.png)

画像ファイルがurlの形で組み込まれています。

## file-loader
もし、この画像ファイルの容量が大きかった時に`index.html`に埋め込むのは得策ではありません。
そこで`file-loader`を使ってこの問題を解決します。

まずは、`file-loader`を入れます

```
npm install file-loader@5.0.2 -D
```

次に`webpack.config.js`で設定を追加します。

```webpack.config.js
// loaderの設定
  module: {
    rules: [
      {
        // 適用するファイルの拡張子を正規表現で記述
        test: /\.css$/,
        // 使用するloaderを指定
        use: ["style-loader", "css-loader"]
      },
        //ここを追加
      {
        // 適用するファイルの拡張子を正規表現で記述
        test: /\.(png|jpg|gif)$/,
        // 使用するloaderを指定
        loader: "file-loader",
        // 使用するloaderの追加設定
        options: {
          //出力時のファイル名
          name: "[name].[ext]",
          //出力場所の指定
          outputPath: "images/"
        }
      }
    ]
  },
```

実行して、ブラウザで確認をするとhtmlから画像のファイルパスを指定してます

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/251047/bea73768-3e9a-383b-bc37-6449860f2855.png)

実際に画像ファイルをhtmlファイルとは別でとってきています。Networkで`url-loader`と`file-loader`を比較してみます。

`file-loader`ではTypeが`text/plain`でテキストを読み取っている？

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/251047/850e012b-45e2-e49b-8b77-a37d64c4bb94.png)


`url-loader`を使った場合はTypeが`jpeg`でデータを読みとっている？

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/251047/3955d4aa-e48d-aebb-848d-332c884e72a0.png)

# TypeScript

次は、TypeScriptを使って書いたファイルを出力時にJavaScriptにコンパイルする方法を書いていきます。

まずは今までのコードをTypeScriptに書き換えます。
TypeScriptで記述するために必要なパッケージを入れます。

```
npm i -D typescript@3.7.5
```

ここでは、TypeScriptを使った開発ができればいいので
四則演算のファイルを使います
ここでは加算の例のみ記します

```add.ts

export function add(a: number, b: number) {
  console.log(a + b);
}
```

```app.ts

import { add } from "../modules/add";
import { subtract } from "../modules/subtract";
import { multiply } from "../modules/multiply";
import { divide } from "../modules/divide";

add(1, 2);
subtract(1, 2);
multiply(2, 5);
divide(10, 2);
```

## ts-loader

TypeScriptコードをJavaScriptコードにコンパイルするのに必要なLoaderが**ts-loader**です。
まずは、今までのJavaScriptコードをTypeScriptコードにします。

```
npm install -D ts-loader@6.2.1
```

次は`webpack.config.js`の設定です。追加部分だけを記します。

```webpack.config.js
entry: "./src/ts/app.ts",
module: {
  rules: [
      {
        test: /\.ts$/,
        use: "ts-loader"
      }
   ]
},
resolve: {
 // import時の拡張子省略
 extensions: [".ts", ".js", ".json"]
}
```
### resolve
ここで指定しているものは、import関連の設定ができます。
**extensions**ではimport文のPathの拡張子を省略したいものを記します。
デフォルトだと`.js`と`.json`が指定されていますが、明示的に指定するときはこの2つも含める必要があります。

最後に、TypeScriptのコンパイルについての設定ファイルを作ります

```
npx tsc --init
```

これで実行してみてください！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/251047/246a9d87-a0af-113c-6614-30941e9acdc2.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/251047/e601bea4-c43a-b974-4668-bec59b77ecb1.png)

# 使ってる感が出できた!

ここまでやってきて、webpackを使ってる感じが出てきました！

次の記事ではBabelとPluginと仲良くなりたいと思います。

何か、ご意見ありましたら教えてくれると嬉しいです。

最後にファイル構成を示しておきます。

```
 webpack-friendly-basic
 ├ ─ ─ node_ modules
 ├ ─ ─ package.json
 ├ ─ ─ package-lock.json
 ├ ─ ─ dist
 │     ├ ─ ─ bundle.js
 │     └ ─ ─ index.html
 ├ ─ ─ src
 │     ├ ─ ─ ts
 │     │     └ ─ ─ app.ts
 │     └ ─ ─ modules
 │           ├ ─ ─ add.ts
 │           ├ ─ ─ subtract.ts 
 │           ├ ─ ─ multiply.ts 
 │           └ ─ ─ divide.ts      
 ├ ─ ─ tsconfig.json 
 └ ─ ─ webpack.config.js
```