てっしーの雑記

主に技術系のネタを

WebフレームワークでWebpackを使ってみよう〜Laravel+Webpack+Vue.js編〜

改めてフロントエンド開発の勉強をし直そうということでWebpackをはじめてみました
タイトルの「Laravel+Webpack+Vue.js編」とある通り、他の言語・フレームワークでも試して比較をしてみたいと思っています
LaravelはWebpackをラッパーしたLaravel MIXがデフォルトのようなのでこちらを使っていきます

Webpackとは

JavaScriptファイルをまとめる高機能なモジュールバンドラーでまとめることでウェブページのHTTPリクエストの数を減らしたり、高度なウェブアプリケーションの開発に役立つらしい
イマドキのフロントエンドエンジニアになるには必要な技術みたい
自動テストを導入しやすいといったメリットがあるのかなー...
よくわかっていません。。。

作るもの

Vus.jsの以下のサンプルを表示させてみようと思います

jp.vuejs.org

環境

以下の環境で動かしています

  • macOS High Sierra
  • PHP 7.1.7
  • Laravel Installer 2.0.1
  • Laravel 5.6.3
  • Node.js v9.5.0
  • nmp 4.0.5
  • Webpack

以下のコマンドを参考にインストールします

brew install php71
brew install composer
composer global require "laravel/installer"

brew install node
brew link node
npm install webpack -g

Laravelのインストール

以下のコマンドでプロジェクトを作成します

composer create-project --prefer-dist laravel/laravel laravel-webpack-vue

ローカル開発サーバを起動して http://localhost:8000 にアクセスしてLaravel初期画面が表示されるか確認します

php artisan serve

フロントエンドのインストール

packege.json に記載されているモジュール類をインストールします

npm install

MIXの実行

以下のコマンドでコンパイルを行います
devwatch に変えて実行しておくと関連ファイルの監視を行い変更を感知すると自動でコンパイルを行ってくれます

npm run dev

サンプル画面

Vue.jsのサンプル画面を作成していきます

routes/web.php を修正し index 画面を用意します

Route::get('/', function () {
    return view('index');
});

resources/viewsindex.blade.php を作成します

<!doctype html>
<html lang="{{ app()->getLocale() }}">
    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <link rel="stylesheet" href="css/app.css"/>
        <title>laravel-webpack-vue</title>
    </head>
    <body>
        <div id="app">
            <!-- item template -->
            <script type="text/x-template" id="item-template">
            <li>
                <div
                :class="{bold: isFolder}"
                @click="toggle"
                @dblclick="changeType">
                @{{ model.name }}
                <span v-if="isFolder">[@{{ open ? '-' : '+' }}]</span>
                </div>
                <ul v-show="open" v-if="isFolder">
                <item
                    class="item"
                    v-for="(model, index) in model.children"
                    :key="index"
                    :model="model">
                </item>
                <li class="add" @click="addChild">+</li>
                </ul>
            </li>
            </script>

            <p>(You can double click on an item to turn it into a folder.)</p>

            <!-- the demo root element -->
            <ul id="demo">
            <item
                class="item"
                :model="treeData">
            </item>
            </ul>
        </div>
        <script src="js/app.js"></script>
    </body>
</html>

resources/assets/componets/js/app.jstree-viewサンプルソースを記載します

require('./bootstrap');

window.Vue = require('vue');

// demo data
var data = {
    name: 'My Tree',
    children: [
        { name: 'hello' },
        { name: 'wat' },
        {
            name: 'child folder',
            children: [{
                    name: 'child folder',
                    children: [
                        { name: 'hello' },
                        { name: 'wat' }
                    ]
                },
                { name: 'hello' },
                { name: 'wat' },
                {
                    name: 'child folder',
                    children: [
                        { name: 'hello' },
                        { name: 'wat' }
                    ]
                }
            ]
        }
    ]
}

// define the item component
Vue.component('item', {
    template: '#item-template',
    props: {
        model: Object
    },
    data: function() {
        return {
            open: false
        }
    },
    computed: {
        isFolder: function() {
            return this.model.children &&
                this.model.children.length
        }
    },
    methods: {
        toggle: function() {
            if (this.isFolder) {
                this.open = !this.open
            }
        },
        changeType: function() {
            if (!this.isFolder) {
                Vue.set(this.model, 'children', [])
                this.addChild()
                this.open = true
            }
        },
        addChild: function() {
            this.model.children.push({
                name: 'new stuff'
            })
        }
    }
})

// boot up the demo
var demo = new Vue({
    el: '#demo',
    data: {
        treeData: data
    }
})

resources/scssapp.scsstree-view サンプルCSSを記載します

// Fonts
@import url("https://fonts.googleapis.com/css?family=Raleway:300,400,600");
// Variables
@import "variables";
// Bootstrap
@import '~bootstrap/scss/bootstrap';
body {
    font-family: Menlo, Consolas, monospace;
    color: #444;
}

.item {
    cursor: pointer;
}

.bold {
    font-weight: bold;
}

ul {
    padding-left: 1em;
    line-height: 1.5em;
    list-style-type: dot;
}

webpack.mix.js を修正します

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

再度 npm run devコンパイルを行いローカル開発サーバを起動してアクセスしてみてVue.jsサイトのサンプルと同じ物が表示されていれば完成です

ソースはGithubに上げてあります github.com