webpack の Loader を試してみる

普段 [webpack](https://webpack.js.org/) を使っているけれども、イマイチおまじない的な部分が多くてよく分かっていないので、ひとまず各 Loader が何をしているのか試してみたメモ。

自分が使いそうな Loader しか試していないのであしからず。

webpack.config.js の内容は以下の通り。[^config]

[^config]: テスト用ということで Module 定義を省略している (require 時に指定) ので注意。

```js:webpack.config.js
module.exports = {
  entry: './index.js',
  output: {
    filename: 'output.js'
  }
};
```


## css-loader
[webpack-contrib/css-loader](https://github.com/webpack-contrib/css-loader)

CSS ファイル内の `@import`、`url()` を解決しながら読み込む。

```css:input.css
@import './input2.css';

.red {
  background-color: red;
}
```
```css:input2.css
.blue {
  background-color: blue;
}
```
```js:index.js
window.css = require('css-loader!./input.css');
// => [[6, ".blue {\r\n  background-color: blue;\r\n}\r\n", ""], [4, ".red {\r\n  background-color: red;\r\n}\r\n", ""]]
//    (各要素の最初の数字は webpack 後のモジュールのインデックス)
```

### 使いそうなオプション

|オプション|値|説明|
|---------|---|----|
|minimize|{Boolean&#124;Object}|CSS を minify する場合は true、またはオプションをオブジェクトで渡す|
|sourceMap|{Boolean}|SourceMap を出力するかどうか|


## extract-loader
[peerigon/extract-loader](https://github.com/peerigon/extract-loader)

css-loader、html-loader と組み合わせて使用し、各 Loader で読み込んだ内容を取り出す時に使用する。
取り出した内容は別の Loader (file-loader 等) に渡してやらないとビルドエラーになる。
なぜか `@import` を含む CSS を css-loader 経由で渡すとエラーになったので、`@import` 等を使用しないか、css-loader 以外で `@import` を解決させるのが良いかも。

```css:input2.css
.blue {
  background-color: blue;
}
```
```js:index.js
window.extract = require('raw-loader!extract-loader!css-loader!./input2.css');
// => ".blue {\r\n  background-color: blue;\r\n}\r\n"
```

### 使いそうなオプション
特になし。


## file-loader
[webpack-contrib/file-loader](https://github.com/webpack-contrib/file-loader)

コンテンツの内容のハッシュ値を計算しつつ、内容をファイルに保存する。[^file1]

[^file1]: ファイル出力の有無はオプションで切り替え可。

```:input.txt
I'm TEXT document.
```
```js:index.js
window.file = require('file-loader!./input.txt');
// => "ade07100af617adbeafd58fa8727fb42.txt"
```

### 使いそうなオプション

|オプション|値|説明|
|---------|---|----|
|name|{String&#124;Function}|保存時のファイル名。省略時はファイル名が MD5 ハッシュ値になるため、指定はほぼ必須|
|outputPath|{String&#124;Function}|ファイルの保存先|
|emitFile|{Boolean}|ファイルを保存するかどうか|


## raw-loader
[webpack-contrib/raw-loader](https://github.com/webpack-contrib/raw-loader)

ファイルの内容をそのままテキストとして読み込む。
ファイルはテキストファイル、バイナリファイルを問わない。

```:input.txt
I'm TEXT document.
```
```js:index.js
window.raw = require('raw-loader!./input.txt');
// => "I'm TEXT document.\r\n"
```


### 使いそうなオプション
オプションなし。


## sass-loader
[webpack-contrib/sass-loader](https://github.com/webpack-contrib/sass-loader)

[Sass](http://sass-lang.com/) をコンパイルする。
実行時には [node-sass](https://github.com/sass/node-sass) が必要。
取り出した内容は別の Loader (css-loader 等) に渡してやらないとビルドエラーになる。


```sass:input.scss
@import 'input2';

.red {
  .blue {
    background-color: blue;
    color: red;
  }
}
```
```css:input2.css
.blue {
  background-color: blue;
}
```
```js:index.js
window.sass = require('css-loader!sass-loader!./input.scss');
// => [[10, ".blue {\n  background-color: blue; }\n\n.red .blue {\n  background-color: blue;\n  color: red; }\n", ""]]
```

パスの頭に `~` (`~/` ではないので注意) を付けることで `node_moduels` 配下のファイルを参照させることも可能。

```css:例
@import "~bootstrap/dist/css/bootstrap";
```

### 使いそうなオプション
[node-sass のオプション](https://github.com/sass/node-sass#options) をそのまま指定可能。

|オプション|値|説明|
|---------|---|----|
|outputStyle|'nested' &#124; 'expanded' &#124; 'compact' &#124; 'compressed'|出力する CSS のレイアウトスタイル。minify するのであれば何を指定しても関係ない。|
|sourceMapEmbed|{Boolean}|SourceMap を埋め込むかどうか|


## style-loader
[webpack-contrib/style-loader](https://github.com/webpack-contrib/style-loader)

Style タグを DOM に追加するコードを生成する。
css-loader と組み合わせて使用する。
基本的に require すると自動的に Style タグが DOM に追加されるが、`style-loader` の代わりに `style-loader/useable` を Loader として指定することで、DOM への追加をコードから実行させることも可能。


```css:input.css
@import './input2.css';

.red {
  background-color: red;
}
```
```css:input2.css
.blue {
  background-color: blue;
}
```
```js:index.js
window.style = require('style-loader!css-loader!./input.scss');
// => Object {...}
```

### 使いそうなオプション
特になし。


## ts-loader
[TypeStrong/ts-loader](https://github.com/TypeStrong/ts-loader)

[TypeScript](https://www.typescriptlang.org/) をコンパイルする。
ビルドには `tsconfig.json` が必要。

```ts:input.ts
const str = 'TypeScript';
const str2 = `I'm ${str} document.`
export default str2;
```
```js:index.js
window.ts = require('ts-loader!./input.ts');
// => "I'm TypeScript document."
```

### 使いそうなオプション
特になし。


## url-loader
[webpack-contrib/url-loader](https://github.com/webpack-contrib/url-loader)

コンテンツを Base64 エンコーディングする。
コンテンツのサイズが閾値以上の場合、`fallback` オプションに指定した Loader (デフォルトは file-loader) に処理を委譲する。

```:input.txt
I'm TEXT document.
```
```js:index.js
window.url = require('url-loader!./input.txt');
// => "data:text/plain;base64,SSdtIFRFWFQgZG9jdW1lbnQuDQo="
```

### 使いそうなオプション
|オプション|値|説明|
|---------|---|----|
|limit|{Number}|Base64 エンコーディングするサイズの上限|
|mimetype|{String}|ファイルの MIME タイプ。省略時は拡張子から判別される|