Laravel MixでDataTablesを良い感じに扱う


# 前書き
Laravel Mixを使ってDataTablesを使ってみる手順が見つからなかったので残しておきます。
Mixを使う事により、npm管理したり、モジュール化されたり、jsをまとめたり、まとまったjsのキャッシュをコントロールしたりできます。

Laravel Mixの概要についてはこちら。基本的なセットアップは済んでいるものとして説明します。
https://readouble.com/laravel/5.4/ja/mix.html

DataTablesについてはこちらを参照してください。
https://qiita.com/nissuk/items/7ac59af5de427c0585c5


### 環境
MacVagrant上で構築したCentOS
Laravel5.4（5.4で検証しましたが、他のバージョンでも同じように使えると思います）
yarn（互換性があるのでnpmでも同じになるはずです）
（yarnとnpmコマンドの互換はこちら https://qiita.com/masterkey1009/items/50f95b1187646a7db385）


# 手順（基本編）
### packageの取得
https://datatables.net/download/index
DataTablesは使い方によって対象のpackageが複数用意されています。
上記画面で自分が使いたい機能を選択して、一番下のタブで自分が使いたい環境（今回はyarn）のタブを選ぶとコマンドが表示されます。
<img width="904" alt="スクリーンショット 2017-10-09 19.15.57.png" src="https://qiita-image-store.s3.amazonaws.com/0/32169/9afc6b77-0350-4e2c-b313-7af2a1b962fc.png">
これに従ってコマンドを実行します。

`yarn add datatables.net-bs`


### app.jsへの組み込み
今回はapp.jsにdatatablesを取り込むようにします。（やりたい事によって適時調整してください。）
デフォルトだと、resouces/assets/js/bootstrap.js（resouces/assets/js/app.jsから参照されています）にjQueryの記述があるので、同じ箇所で読み込むようにします。

```
try {
    window.$ = window.jQuery = require('jquery');

    // datatables
    require('datatables.net-bs');

    require('bootstrap-sass');
} catch (e) {}
```

※マニュアルだと
`    require('datatables.net-bs')();` という書き方をしていますが、後述の日本語化が動きませんでしたのでこの記述にしています。

### Laravel Mixを使ってコンパイル
`yarn run dev`

を実行すると、public/js/app.jsが生成されます。中を確認して、DataTablesのスクリプトが含まれていれば成功です。


### DataTablesを使う
使いたい画面で対象の要素に対して指定します。app.jsは全画面固定で読み込まれている前提です。

```
<script>
	window.jQuery(function($){
		$("#hoge-table").DataTable();
	});
</script>
```

※こちらもマニュアルだと`$(document).ready`を使っていますが、nissukさんの記事を参考に作ったので `jQuery()`を使っています。

これで基本的な動きはOKなはずですが、日本語化してみます。

# 手順（日本語化）
languageの取得ですが、通常の方法だとurlを指定するので別ファイル呼び出しになり、ネットワークのオーバーヘッドがかかります。
せっかくなので、packageを取得して、mixでまとめます。

### packageの取得
日本語化ファイル（Japanese.json）もnpmから取得する事が可能です。

`yarn add drmonty-datatables-plugins`


### app.jsへの組み込み
#### 完成形
```
    // datatables
    require('datatables.net-bs');

    // デフォルトの設定を変更
    var language = require('json-loader!drmonty-datatables-plugins/i18n/Japanese.json');
    jQuery(function($){
        $.extend(true, $.fn.dataTable.defaults.oLanguage, language);
    });
```

#### 解説
まず、url指定の場合どのように日本語化されるのか、DataTablesの処理を追ってみます。
元処理

```
    $.extend( $.fn.dataTable.defaults, { 
        language: {
            url: "http://cdn.datatables.net/plug-ins/9dcbecd42ad/i18n/Japanese.json"
        } 
    }); 
```

`$.extend`はobjectをマージする処理です。（https://www.tam-tam.co.jp/tipsnote/javascript/post3853.html）
なので、```$.fn.dataTable.defaults.language.url = "http://cdn.datatables.net/plug-ins/9dcbecd42ad/i18n/Japanese.json"```
のような事をしています。
設定された`language.url`の処理を頑張って追うと

```
if ( oLanguage.sUrl )
{
	/* Get the language definitions from a file - because this Ajax call makes the language
	 * get async to the remainder of this function we use bInitHandedOff to indicate that
	 * _fnInitialise will be fired by the returned Ajax handler, rather than the constructor
	 */
	$.ajax( {
		dataType: 'json',
		url: oLanguage.sUrl,
		success: function ( json ) {
			_fnLanguageCompat( json );
			_fnCamelToHungarian( defaults.oLanguage, json );
			$.extend( true, oLanguage, json );
			_fnInitialise( oSettings );
		},
		error: function () {
			// Error occurred loading language file, continue on as best we can
			_fnInitialise( oSettings );
		}
	} );
	bInitHandedOff = true;
}
```

前後処理はありますが、ひとまずjsonを`$.extend( true, oLanguage, json );`としてあげれば良さそうです。

というわけでpackageで取得してあるjsonを読み込むわけですが、ただrequireするだけだとjsとして解釈されてしまい、上手く読み込むことができません。

実は、Laravel Mixがラップしているwebpackにはjsonを読み込む機能があります。
http://thujikun.github.io/blog/2014/12/07/webpack/
※他にも色々なローダーがあるので、Mixを使う上でWebPackの知識があると、使い方の幅が広がりそうです。

json-loaderを指定して、

`    var language = require('json-loader!drmonty-datatables-plugins/i18n/Japanese.json');`

でjsonファイルを読み込んで、jsのobjectとして取得する事が可能です。
後はこれをdataTableの変数に渡してあげればOKです。

`
    jQuery(function($){
        $.extend(true, $.fn.dataTable.defaults.oLanguage, language);
    });
`

※ 元の処理だと前後処理がありましたが、除外しても動きました。しかし、何かしらの問題が起きる可能性があります。

# まとめ
というわけで、DataTablesをLaravelMixを使うことでモダンなjs環境に取り込む事ができました。他のライブラリを使う際にも応用が効くと思います。
結局webpackの知識が必要になるのですが、使いこなすと他にも色々できそうです。