JavaScript
Vue.js
webpack
nodist
Laravel-Mix

Laravelを使っていないプロジェクトでLaravel Mixを導入した話

More than 1 year has passed since last update.

ラクス Advent Calendar 2017 の6日目の記事です。昨日は@fnzzzさんによる「 VUIのデザインについて考察してみた 」でした。

本日はこの記事でQiita初投稿となります、@amderbarです。


はじめに

先日、個人的に作っているWebアプリケーションにLaravel Mixを導入しましたのでそのお話です。大筋は「Laravel Mixでwebpackをもっと簡単に使う方法」に従っていますが、1点だけハマった点があったのでそこも含めてお話しします。


Laravel Mix とは

本題に入る前に簡単にLaravel Mixのご紹介です。

Laravel Mix はPHPフレームワーク「Laravel」に内包されるwebpackのAPIラッパーです。webpackは便利なようですが、ちょっと見ただけでも自由度が高い分設定が複雑で敷居が高い印象を受けます。

ですがLaravel Mixを使えば煩わしい設定に悩むことなく簡単に導入でき1、運用もらくちんです。

しかもLaravel自体はこれの使用を強制しているわけでもなく、Laravel Mixの方もLaravelに密結合しているわけではありません。Laravel Mixだけを拝借し、Laravel本体を使わないプロジェクトに組み込むこともできるんです2


要件

導入したプロジェクトは以下のような構成になっていました。


環境

開発に使用しているマシンのOSはWindows10、Node.js、npmはインストールしていませんでした。

サーバー側プログラムではPHPを使用。autoloadを使いたかったのでcomposerは入れましたが、Laravelその他フレームワークは使っていません。

フロント側ではjQueryVue.jsを読み込んで使用していましたので、Laravel Mix導入後もそれらを使用できるようにします。


ディレクトリ構成

プロジェクトルート

├─app
│ ├─Actions
│ ├─Processes
│ ├─Requests
│ └─Views : 各画面のHTMLの格納場所
├─lib
├─public : 公開ディレクトリ
│ │ index.php
│ ├─css
│ ├─img
│ └─js
├─setup
├─storage
├─tests
└─vendor


導入の流れ


NodistのインストールとNode.js, npmの入手

Windows環境でNode.jsを使うことになるので、NodistをインストールしてNode本体とnpmを入手しましょう。GitHubリリースページからインストーラをダウンロードしてインストールします。

Nodistについてはこちらを参考にさせていただきました。ただNodistのGitHubのリポジトリを見に行くと


[LOOKING FOR A MAINTAINER :) ]


と書かれていていて今後使い続けられるかどうか不安な感じですが…。

ともあれ、インストールしてパスを通したら、コマンドが使えるかを確認します。

$ nodist -v

0.8.8

せっかくなのでNodeとnpmは最新版を使うことにしましょう。

$ nodist latest

$ nodist
(x64)
7.2.1 (global: v7.2.1)
> 9.2.0 (env: 9.2.0)
$ nodist npm latest
$ node -v
v9.2.0
$ npm -v
5.6.0


package.jsonを作成してLaravel Mixをインストールする

LaravelのGitHubリポジトリからpackage.jsonをもらってきて、プロジェクトのルートディレクトリに配置します。

他のパッケージを使っている、ないし使いたい場合はそれをdependenciesに含めます(devDependenciesでもいいですが)。今回はeslintも一緒に入れることにしました3


package.json

{

"private": true,
"scripts": {
"dev": "npm run development",
"development": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
"watch": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --watch --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
"watch-poll": "npm run watch -- --watch-poll",
"hot": "cross-env NODE_ENV=development node_modules/webpack-dev-server/bin/webpack-dev-server.js --inline --hot --config=node_modules/laravel-mix/setup/webpack.config.js",
"prod": "npm run production",
"production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --no-progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js"
},
"devDependencies": {
"axios": "^0.17",
"bootstrap-sass": "^3.3.7",
"cross-env": "^5.1",
"eslint": "^4.9.0",
"jquery": "^3.2",
"laravel-mix": "^1.0",
"lodash": "^4.17.4",
"vue": "^2.5.7"
}
}

package.jsonができたなら、以下のコマンドでパッケージインストールします。

$ npm install

依存関係でやたらパッケージがインストールされますが、少し待てば終わります。


webpack.min.jsの編集

Laravel Mixはwebpackの設定ファイルを自分で作らなくてよく、コンパイル対象のアセットを指定するファイル「webpack.mix.js」を作成するだけです。生のwebpackはこの辺の設定がめんどうっぽいですが、Laravel Mixなら簡単ですね。

これもLaravelのGitHubリポジトリからもらって来てルートディレクトリに配置してしまうのがらくちんでいいです。

いいのですが、そのままだとハマります。

具体的には後述のコマンドでビルドしようとすると進捗95%で止まったまま進行しなくなります。さらにmix-manifest.jsonというファイルがpublicディレクトリ下に作られるはずが、なぜかプロジェクトルートディレクトリ下に作られてしまい内容もおかしなものになります。

mix.setPublicPath('public');

これ。Laravelを使っていない場合、ハマりポイントを回避するにはこの一行が必要です。参考サイトでは記載されていませんが、この問題自体はLaravel MixのリポジトリのIssueでも話題に挙がっていていました。

publicPath is not set when not using laravel #807

以下は件の文を追加してちゃんと動くようにしたコード。'public'はプロジェクトの公開ディレクトリを指します(webpack.mix.jsからの相対パス指定だと思います)。


webpack.mix.js

let mix = require('laravel-mix');

mix.setPublicPath('public');
mix.js('resources/assets/js/app.js', 'public/js')
.sass('resources/assets/sass/app.scss', 'public/css');


後はサンプルを参考に設定を記述すればOKです。

mix.js(..).sass(..)部分でwebpackでコンパイルするjsファイルとSCSS/Sassファイル、さらに出力するディレクトリを定義しています。画面ごとにファイルを分けたいときなんかも、メソッドチェーンで指定を増やすだけです。


ソースとなるアセットを作成

webpack.mix.jsファイルにコンパイル対象のファイルを定義しましたが、ソースファイルをまだ作っていませんね。webpack.mix.jsでの記述に合わせ、次のようなディレクトリ構造に変更します。

├─app

├─lib
├─public : 公開ディレクトリ
│ │ index.php
│ ├─css
│ ├─img
│ └─js
├─resources ← 追加
│ ├─assets : アセットの格納場所
│ │ ├─js
│ │ │ │ app.js
│ │ │ │ bootstrap.js
│ │ │ └─components
│ │ │ ExampleComponent.vue
│ │ └─sass
│ │ app.scss
│ │ _variables.scss
│ └─views : app下にあったものを移動
├─setup
├─storage
├─tests
└─vendor

resources/assets/下の各種ファイルは例によってLaravelのスカフォードから拝借してきました。


ビルド

いよいよ実際にHTMLで読み込むjsとcssを作ってみます。以下のコマンドでビルドです。

$ npm run dev

ERROR Failed to compile with 2 errors 22:54:13
error in ./resources/assets/sass/app.scss

Module build failed: Error: Node Sass does not yet support your current environment: Windows 64-bit with Unsupported runtime (59)
For more information on which environments are supported please see:
(後略)

……エラーになってしまいました。メッセージを見ると何となくバージョンエラーな感じがします。Nodeを最新版にしたからでしょう。Nodeのバージョンを下げるのも選択肢の一つですが、とりあえず安易にパッケージをアップデートしてみます。

$ npm update

$ npm run dev

DONE Compiled successfully in 7435ms

できました。

できましたが、開発中はこっちの方がいいですね。

$ npm run watch

watchコマンドを使えばソースファイルを編集したら自動でビルド実行してくれます。devやwatchコマンドの初回実行時と違って自動ビルドはすぐ終わるので、ちょこっと変更して動作を見てを繰り返したい時などに便利です。


動作確認

それではサーバーを起動してテストページにアクセスしてみましょう。ここでは以下のようなテストページをpublicディレクトリに用意してみました。


mixtest.html

<!DOCTYPE html>

<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<meta name="csrf-token" content="some_token">
<!-- Styles -->
<link href="css/app.css" rel="stylesheet">
<title>Document</title>
</head>
<body>
<main id="app">
<example-component></example-component>
</main>

<!-- Scripts -->
<script src="js/manifest.js"></script>
<script src="js/vendor.js"></script>
<script src="js/app.js"></script>
</body>
</html>


<meta name="csrf-token"~がないとjsで警告されちゃうので追加しておきます。

問題がなければ以下のようなページが表示されるはずです。

テストページのスクショ

これで導入できました。やったね! 後は自分の作りたいものを実装するだけです。


まとめ


  • Laravel Mixはwebpackの使用をらくちんにしてくれる。

  • けれどLaravelを使っていない場合は必須で付け加えないといけないー文があるので注意!


参考





  1. この記事の話は導入でハマった話なので悩みどころがないわけではありませんが、解決策が分かっているなら簡単です。 



  2. MIT licenseなのでその辺も問題ない、はずです。 



  3. 別に最初からpackage.jsonに書いておかなくても、あとからnpm install hoge --save-devとした方がその時の最新版を入れてくれるのでいいかもしれませんね。