Laravel 6.x  【Laravel-mix】 で Material Design Bootstrap を使用する【npmでインストール】

#npm installでLaravelにMaterial Design Bootstrapをインストール

#はじめに
この記事はプログラミングをはじめたばかりの素人が、できたことをメモするのに利用しています。
内容には誤りがあるかもしれません。

<font color="red">**【追記 2020年11月5日】**</font>
<font color="red">この記述だけでは問題があることが判明したため、新規で項目を追加し、うまくいった方法を追記掲載しました。</font>

内容は　<font color="red">**【追記】2020年11月5日問題発生！**</font>　をご確認ください。

##作業環境
Windows 10
Laravel : 6.18.35
Laravel/ui : 1.0
Laravel-mix : 5.0.1
Bootstrap : 4.0.0
MDBootstrap : 4.19.1
chart.js : 2.9.3
XAMPP
PHP : 7.4.3
Visual Studio Code

##前提
当方環境ではlaravel/uiを使用し、

```PHP
php artisan ui vue --auth
```

VueとBootstrapを事前にイントールしています。


##インストール方法
npmでインストールを行います。
ターミナルで以下を実行します。

```
npm install mdbootstrap
```

続けて以下を実行。

```
npm install --save chart.js
```

resources>sass>のapp.scssを開き、以下を追記する。

```CSS:app.scss
@import "~mdbootstrap/scss/mdb-free";
```

再度ターミナルで以下を実行。

```
npm run watch-poll または npm run dev
```

##headとbodyへの記述

head内に以下を追記します。

```HTML
<link rel="stylesheet" href="{{ mix('css/app.css') }}">
```

bodyの一番最後に以下を追記します。

```HTML
<script src="{{ mix('js/app.js') }}"></script>
```

##エラーについて
インストールするまでに、色々なサイトを見て記述を行いましたが、最終的にはシンプルな記述で当方では成功しました。

###mdbootstrapのフォルダが見つからない
npmでインストールした物は、node_modulesに格納されるらしいのですが、いくら探してもエディター上では見当たりませんでした。
エディターからではなく、普通にフォルダを開いて検索すると、問題無くフォルダが存在していたので、エディターを再起動した所解決しました。
これで時間を取られました。どれだけ記述を変えてもフォルダがないとエラー表示。

###This dependency was not found:
npm run dev を行った所エラーが発生しました。

```CSS
 ERROR  Failed to compile with 1 errors
This dependency was not found:

* chart.js in ./node_modules/mdbootstrap/js/mdb.min.js

To install it, you can run: npm install --save chart.js
```

インストールしろって書いてあるので、言われた通りインストールし、うまくいきました。

```
npm install --save chart.js
```

##参考にしたページ
https://cpoint-lab.co.jp/article/201905/9511/
bootstrap-material-designのインストールに関して解説してありまが、当方ではうまくいきませんでした。

https://qiita.com/MURAMASA2470/items/4fc94577eee8cc1b3811
結局mdbootstrapのインストールで落ち着いたので、全く試してません。

https://qiita.com/ntm718/items/af4420a0a4bf48f1f50e
Laravel 5.5で、当方の環境と違うせいかうまくいきませんでした。
記事内にsetting bootstrap.jsの記述がありますが、当方の環境ではあっても無くても変化なしでした。
また、import app.scssの記述ですが、


```CSS
// Bootstrap
@import "../../../node_modules/mdbootstrap/css/style.css";
@import "~mdbootstrap/scss/mdb-free";
@import "../../../node_modules/mdbootstrap/css/bootstrap.min.css";
```

当方とディレクトリが違った為、以下に修正しましたが、

```CSS
// Bootstrap
@import "../../node_modules/mdbootstrap/css/style.css";  //修正
@import "~mdbootstrap/scss/mdb-free";
@import "../../node_modules/mdbootstrap/css/bootstrap.min.css";  //修正
```

エラーが発生してしまう為、結局真ん中の記述のみ使用する形になりました。
削除した2つの記述が必要な物なのかがよくわかりませんでした。

#<font color="red">【追記】2020年11月5日問題発生！</font>

<font color="blue">ここから先の文章は、上で説明した内容だけでは問題が発生したため、その改善策として追記したものです。</font>

この問題は制作環境によって引き起こされている可能性もあるため、環境によっては発生しないかもしれません。

#発生した問題について

オリジナルのフォームのデザイン作成中に問題が発生しました。

デザインは以下のリファレンスを元に作成してます。
https://mdbootstrap.com/docs/jquery/forms/customization/

参考にしたのはその中の`A form within a card`で、カーソルを項目に合わせると中の文字が上に自動的に移動するようになっています。
![form1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/760252/af5a7787-bea7-8948-cd86-f61486aea739.jpeg)

Your nameにカーソルを合わせると、
![form2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/760252/ee74469f-6a82-dff2-c002-a3ce05ff075a.jpeg)

文字が小さくなり上に文字(Your name)が移動する。

このフォーマットを元に以下のようなデザインを作成したところ、
![form3.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/760252/9158264d-daf1-8645-dd44-e0f0d5daf924.jpeg)

問題が発生しました。

内容としては、カーソルを合わせても文字が移動しません。
![form4.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/760252/ac683d77-9d27-1013-2f94-39c7477dda29.jpeg)

移動するどころか被って邪魔です。

#原因

<font color="blue">リファレンスの動作をデベロッパーツールを使用し確認したところ、`class`に対して`active`という名称を追加することでコントロールしていることがわかりました。</font>

そこで、JavaScriptに問題があると考え、問題のあるスクリプトを探すことにし、検証した結果、原因がmdb.min.jsにあることがわかりました。

#原因究明の為にやたこと

##CDNの利用

記述に問題がないよう、リファレンスのサンプルを丸々コピーして検証することにしました。
ちなみに、コピーしたサンプルでも同じ状況でした。

まず、Laravel-mixの記述を一度コメントアウトし、CDNに切り替えて動作を確認しました。

追記したCDNは以下の通りで、`<head>`内に

```HTML
<!-- Font Awesome -->
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.8.2/css/all.css">
<!-- Google Fonts -->
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap">
<!-- Bootstrap core CSS -->
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.5.0/css/bootstrap.min.css" rel="stylesheet">
<!-- Material Design Bootstrap -->
<link href="https://cdnjs.cloudflare.com/ajax/libs/mdbootstrap/4.19.1/css/mdb.min.css" rel="stylesheet">
```

`</body`>の直前に、

```HTML
<!-- JQuery -->
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<!-- Bootstrap tooltips -->
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.4/umd/popper.min.js"></script>
<!-- Bootstrap core JavaScript -->
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.5.0/js/bootstrap.min.js"></script>
<!-- MDB core JavaScript -->
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/mdbootstrap/4.19.1/js/mdb.min.js"></script>
```

を記述しました。

<font color="blue">結果は問題なく動作することを確認しました。</font>

##CDNとLaravel-mixを組み合わせて利用

CDNでは問題なかったので、Laravel-mixと併用しながら検証をすすめました。

まず、`<head>`内の`Laravel-mix`の記述を元に戻し、`<head>`内のCDNを全て削除しました。
削除した理由は、`<head>`で読み込んだCDNの内容は`Laravel-mix`で問題なく動作しているからです。

`<head>`内のCDNを全て削除しても、<font color="blue">JavaScript側の読み込みがCDNであれば問題がないことがわかりました。</font>

次に`</body`>の直前の`Laravel-mix`の記述を元に戻し、動作に問題がないと確認できている以下の記述だけ削除しました。

```HTML
<!-- JQuery は別のページで問題なく動作しているので削除 -->
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<!-- Bootstrap tooltips Bootstrapのモーダルが別ページで動作しているので削除 -->
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.4/umd/popper.min.js"></script>
<!-- Bootstrap core JavaScript これも同じ理由で削除 -->
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.5.0/js/bootstrap.min.js"></script>
```

残った記述が以下のようになります。
<font color="red">※一部のみ抜粋。</font>

```HTML
    <!-- Bootstrap Font Awesome-->
    <link rel="stylesheet" href="{{ mix('css/app.css') }}">

</head>

<body>

    <!-- Bootstrap Vue JavaScript -->
    <script src="{{ mix('js/app.js') }}"></script>
    <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/mdbootstrap/4.19.1/js/mdb.min.js"></script>
    
</body>
```

**<font color="red">★ポイント★</font>**
スクリプトの記述ですが、CDNを先に書いて`Laravel-mix`を後に記述したところ、デベロッパーツールで確認するとエラーが多数発生し、動作しませんでした。<font color="red">記述の順番が重要なようです。</font>

#解決の為にやってうまくいかなかったこと

##Laravel-mixに全てを統合

上の検証から、`mdb.min.js`が解決の為に必要なことがわかったので、このファイルがあるかどうかを探すことにしました。
npmでインストールしたものは、`node_modules`の中にあるので同じ名前のファイルがないか確認した所、ありました。

![mdb.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/760252/6a648a0c-b644-6fcd-d40d-987b8bb156e3.jpeg)

`node_modules>mdbootstrap>js`の中にあります。

このファイルを読み込む為に色々な記述を試しましたが、**<font color="red">結論`Laravel-mix`で１つにまとめたファイルを読み込んでも動作しません。</font>**

以下が試した記述です。

##パターン①

resources>js 内のapp.jsに以下を追記しコンパイル。

```JavaScript:app.js
require("mdbootstrap");
```

<font color="red">結果:問題解決せず。</font>

**<font color="red">★ポイント★</font>**
`./`を先頭に記述しない場合は、node_modulesの中から読み込んでくれるそうです。
でも失敗でした。

##パターン②

app.jsは元に戻し、同じディレクトリのbootstrap.jsを以下に修正

```JavaScript:bootstrap.js
try {
    window.Popper = require("popper.js").default;
    window.$ = window.jQuery = require("jquery");


    require("bootstrap");
    require("mdbootstrap");

} catch (e) {}
```

<font color="red">結果:問題解決せず。</font>
記述してる場所が違うだけで、やってること一緒なので改善しませんでした。

##パターン③

bootstrap.jsを以下に修正

```JavaScript:bootstrap.js
try {
    window.Popper = require("popper.js").default;
    window.$ = window.jQuery = require("jquery");


    require("bootstrap");
    require("./../../node_modules/mdbootstrap/js/mdb.min.js");

} catch (e) {}
```

<font color="red">結果:問題解決せず。</font>

ファイルが読めていないのではと思い、直接ファイルを指定してみましたが、ダメでした。

##その他

他に直接`node_modules`の`mdb.min.js`を読み込む等試してみましたが、コンパイルはできているようですがやはり動作はしませんでした。

#解決策

以上の内容から、コンパイルしているファイルが競合しているか、JavaScriptの読み込みの順番に問題があると考え、`mdb.min.js`を別で読み込むことにしました。
ファイル自体は`node_modules`内にあるので、これをきちんと利用します。

##解決方法

`webpack.mix.js`を以下のように変更します。

**<font color="blue">変更前</font>**

```JavaScript:webpack.mix.js
mix.js('resources/js/app.js', 'public/js')
    .sass('resources/sass/app.scss', 'public/css');
```

**<font color="red">変更後</font>**

```JavaScript:webpack.mix.js
mix.js('resources/js/app.js', 'public/js')
    .sass('resources/sass/app.scss', 'public/css')
    .copy('node_modules/mdbootstrap/js/mdb.min.js', 'public/js')
    .version();
```

`webpack.mix.js`は`Laravel-mix`の読み込み、出力先を決めるファイルです。
※素人の言ってることなので、間違ってるかもしれません。

Laravelの場合、自身で作成したファイル等はpublicディレクトリの中に配置して読み込みます。
その為、

```JavaScript:webpack.mix.js
    .copy('node_modules/mdbootstrap/js/mdb.min.js', 'public/js')
```

この記述で`node_modules`にある`mdb.min.js`のファイルを`public/js`ディレクトリにコピーさせるようにしてあります。
記述が完了したら、ターミナルで以下を実行してください。

```PHP
 npm run dev
```

`public/js`ディレクトリに`mdb.min.js`ファイルが作成されていればOKです。

次に`</body>`直前の記述を以下に修正します。

```HTML
<!DOCTYPE html>
<html lang="ja">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0 shrink-to-fit=no">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <meta name="csrf-token" content="{{ csrf_token() }}">

    <!-- Bootstrap Font Awesome-->
    <link rel="stylesheet" href="{{ mix('css/app.css') }}">

    <title>@yield('title')</title>
</head>

<body>


    <!-- Bootstrap Vue JavaScript -->
    <script src="{{ mix('js/app.js') }}"></script>
    <!-- MDBootstrap JavaScript -->
    <script type="text/javascript" src="/js/mdb.min.js"></script>

</body>

</html>
```

**<font color="red">★ポイント★</font>**
<font color="red">`mdb.min.js`は必ず`Laravel-mix`の後に記述するようにしてください。</font>
逆になるとエラーが発生し、動作しません。

以上です。