Laravel Mixでw2uiを良い感じに扱う（CommonJSに対応していないライブラリを扱う）

# 前書き
w2uiというjQueryのUIプラグインを、Laravel Mixを使って管理しようとしたのですが、苦労したので残しておきます。w2ui以外にも、CommonJSに対応していないライブラリを使う時に応用が効くと思います。

Mixを使う事により、npm管理したり、モジュール化されたり、jsをまとめたり、まとまったjsのキャッシュをコントロールしたりできます。

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

w2uiについてはこちらを参照してください。
[100万行扱えるグリッドw2ui GridとHandsontableの紹介 - Qiita](https://qiita.com/hnakamur/items/052c439674fa92848ada)


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

# バージョンの罠
まず、w2uiのバージョンについて説明する必要があります。
公式ページ（[Home | JavaScript UI - w2ui](http://w2ui.com/web/)） からDownloadしたり、GitHubのmasterを参照すると1.5.rc1が、npmから取得するとstableな1.4が取得されます。

Laravel mixはwebpackをラップしており、CommonJSに対応していればrequireするだけで簡単に動きます。
が、1.4系はCommonJSに対応していないため、単純にrequireしても動きません。
逆に1.5系はnpmに登録されていません。

というわけで、作戦としては2つ考えられます

1. npmから取得した1.4系を頑張ってCommonJS対応して使う
2. 1.5系をダウンロードするなり、url参照するなりする

最終的に作戦2を採用しましたが（実処理が1.5に依存していたため）、途中までこの事実に気が付かずに作戦1も検証していました。というわけで、作戦1についてもいけた所までは公開しておきます。


# 手順 作戦1.npmから取得した1.4系を頑張ってCommonJS対応して使う
### packageの取得
`yarn add w2ui`

### w2ui使う処理
```js
$(window).on('load', function() {
    w2utils.locale('ja-jp.json');

    $('#grid').w2grid({
        name: 'grid',
        recid:'id',
        method: 'GET',
// 省略
    });
    w2ui['grid'].load('hogeAction');
```
色々機能があるのですが、今回はこんな感じの処理にしていました。
`w2tils`や`w2ui`というグローバルな変数がある前提の処理になっています。

### app.jsへの組み込み

```js
    var w2uiModule = require('exports-loader?w2ui,w2utils,w2obj!w2ui');
    window.w2utils = w2uiModule["w2utils"];
    window.w2ui = w2uiModule["w2ui"];
    window.w2obj = w2uiModule["w2obj"];
```
前述の通り、`w2tils`や`w2ui`というグローバルな変数がある事にしないといけません。
1.4系はCommonJSに対応していない（exports記述が無い）ので、`var w2uiModule = require('w2ui');`としても`w2uiModule`は空objectです。

そこで、exports-loaderという特殊なloaderを指定し、取得したい値を指定する事で、w2uiモジュールの値を外部に取り出す事が可能です。exports-loaderはyarn（npm）で取得しておく必要があります。
LaravelMixは内部的にwebpackを使っているため、こういった便利なwebpackの機能を使う事ができます。loaderについてはこちらを参考にしました。
[webpackを使い倒す - Thujikun blog](https://thujikun.github.io/blog/2014/12/07/webpack/)

また、似たようなissueもあがっていたので、同じく参考にしました。
[Compatibility with browserify · Issue #712 · vitmalina/w2ui](https://github.com/vitmalina/w2ui/issues/712)

# 手順 作戦2 1.5系をダウンロードするなり、url参照するなりする
### packageの取得
扱うファイルを固定にしたかったので（本体が更新されても影響しない）、公式ページからダウンロードして、resouces/assets/jsにjsファイルを、resouces/assets/sassにcssファイルを直接配置します。

### w2ui使う処理
作戦1と同じ


### app.jsへの組み込み

```js
    var w2uiModule = require('./w2ui.min.js');
    window.w2utils = w2uiModule["w2utils"];
    window.w2ui = w2uiModule["w2ui"];
```

今度は単純に`require`で取得できます。
以下のような処理がw2uiに記述されていて、CommonJSに対応しているからです。

```js
(function(global, w2ui) {
    if (typeof define=='function' && define.amd) {
        return define(function(){ return w2ui; });
    }
    if (typeof exports!='undefined') {
        if (typeof module!='undefined' && module.exports)
            return exports = module.exports = w2ui;
        global = exports;
    }
    for (var m in w2ui) {
        global[m] = w2ui[m];
    }
})(this, { w2ui: w2ui, w2obj: w2obj, w2utils: w2utils });
```


### app.cssへの組み込み

app.scssに

```scss
@import "w2ui.min.css";
```
と書けばapp.cssにコンパイルされます。


# まとめ

webpackの便利機能を使って、CommonJSに対応していないライブラリを頑張って対応する事もできました。（最終的には作戦2を採用したのですが）

LaravelMixのドキュメントや使用事例はまだ少ないのですが、困った時はwebpackを調査する事で色々対応が可能そうです。