Gulp+Babel+Webpack でVue.js の開発環境を強化する

フロント開発がもっと楽しくなる!Vue.js 学習メモ。Vue.js の単一コンポーネントファイル .vue が使えるように Gulp+Babel+Webpack をいろいろします。

Vue.js はコンパイルしなくてもそのまま Web ブラウザで利用できるのも特徴なんですが、やっぱり .vue ファイルを使ってみたい! 

Node.js と Gulp は一応導入済みと仮定して、.vue でモジュール化させたファイルを Webpack にまとめてもらい Babel でブラウザ用にコンパイルして、Gulp にウォッチしてもらいます。

今のところ必要なモジュール

とりあえず Vue-loader というモジュールが必要になります。package.json を見ると peerDependencies に依存モジュールがあるのですが(自動でインストールされないやつ?)私の場合は今の開発内容だと他に下のモジュールを入れたら動きました。なにやら Webpack だけでもウォッチしてくれるらしいんですけど他でも色々 Gulp 使ってるのでまだ億劫な感じで調べてません…。ホットリロードとか気になります。

  • webpack
  • vue-loader
  • vue-html-loader
  • vue-template-compiler(vueと同じバージョン)
  • css-loader
  • sass-loader (.vue 内で sass/scss を使う場合)

.js ファイルも ES6 で記述するなら別途以下が必要なようです。

  • babel-loader
  • babel-preset-es2015

とりあえず上記あたりの必要なモジュールを package.json に記述するか --save-dev を付けてインストールします。足りなければ足りないとエラーが出るはずなのです(っ'o'c)

gulpfile.js を書く

var gulp = require('gulp');
var webpack = require('webpack');

普通の gulp-webpack じゃなくて Webpack の Ver2 を使いました。Webpack 自体凄い沢山設定があって覚えるの大変そうです。

var webpackBuild = function (opt) {
    var plugins = [
        new webpack.optimize.UglifyJsPlugin({
            sourceMap: opt.map ? true : false,
            compress: {
                warnings: false
            },
        }),
    ];
    webpack({
        entry: './src/js/main.js',
        output: {
            filename: 'bundle.js',
            path: "./dist/js/",
        },
        plugins: opt.min ? plugins : [],
        module: {
            rules: [{
                    test: /\.vue$/,
                    exclude: /node_modules/,
                    loader: 'vue-loader',
                    options: {
                        loaders: {
                            scss: 'vue-style-loader!css-loader!sass-loader?includePaths[]=./src/sass/'
                        }
                    }
                },
                {
                    test: /\.js$/,
                    exclude: /node_modules/,
                    loader: 'babel-loader',
                }
            ]
        },
        devtool: opt.map ? 'source-map' : '',
        resolve: {
            extensions: ['.js', '.vue']
        }
    }, function (error, stats) {});
}
gulp.task('webpack.watch', function() {
    webpackBuild({ map: false, min: false });
});

.vue ファイルの中で SCSS の使用と変数定義用のファイルを @import を出来るようにしました。

watch タスクに登録します。

gulp.task('watch', function() {
    gulp.watch(['./src/js/**/*.js', './src/js/**/*.vue'], ['webpack.watch']);
});

フォルダ構成の例

website
├ src/
│ ├ js/
│ │ ├ components/
│ │ │ └ piyo.vue
│ │ └ main.js
│ └ sass/ とか
├ dist/
│ └ js/

フォルダ構成はこんな感じです。dist の中のファイルだけFTPでアップロードします。public/dist より上に src もってきても良いと思いますが私は自分で好き勝手出来るサイトなので同じところに置いちゃってます。src フォルダで作っているファイルが dist/js/bundle.js に作成されるようになりました(•ө•)ノ

vue-cli の設定を真似てみる

少し後の話なんですが vue-cli を使ってみたら Webpack や ホットリロードの設定が最初からされててフォルダ構成にもあんまり悩まなくて良さそうな感じでした。ランディングページや SPA サイトを作るなら vue-cli で始めるのが良さそうですね~。

私のサイトは SPA 構成じゃなくて vue-cli で作成してもあまり意味が無かったので config を参考にしてちょっと真似して、.vue の中の CSS コードを抽出してファイルに吐くようにしてみました。

var webpack = require('webpack');
var ExtractTextPlugin = require('extract-text-webpack-plugin')
var OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin')

var webpackBuild = function (env) {

  var webpackBaseConfig = {
    cache: true,
    devtool: 'source-map',
    entry: {
      app: './src/main.js',
/* 自分のコード以外をまとめる */
      vendor: ['vue', 'axios', 'tween.js', 'es6-promise', 'lodash']
    },
    output: {
      path: './dist',
      filename: '[name].js',
      publicPath: 'dist'
    },
    resolve: {
      extensions: ['.js', '.vue'],
      alias: {
        '@': path.resolve('src'),
        'vue$': 'vue/dist/vue.common.js'
      }
    },
    module: {
      rules: [
        {
          test: /\.vue$/,
          loader: 'vue-loader',
          include: [path.resolve('src')],
          options: {
            /* vue-loader のオプション CSSを抽出する */
            loaders: {
              'css': ExtractTextPlugin.extract({
                use: ['css-loader'],
                fallback: 'vue-style-loader',
              }),
              'scss': ExtractTextPlugin.extract({
                use: [{
                  loader: 'css-loader'
                },
                {
                  loader: 'sass-loader',
                  options: {
                    includePaths: [path.resolve('src/sass')]
                  }
                }],
                fallback: 'vue-style-loader',
              })
            },
          }
        },
        {
          test: /\.js$/,
          loader: 'babel-loader',
          include: [path.resolve('src')],
        },
      ]
    },
    plugins: [
      new webpack.DefinePlugin({
        'process.env': {
          'NODE_ENV': JSON.stringify(env)
        }
      }),
      /* ライブラリを共有ファイルにする */
      new webpack.optimize.CommonsChunkPlugin({
        name: 'vendor',
        filename: 'vendor.bundle.js',
        minChunks: Infinity,
      }),
      /* JavaScriptを圧縮する */
      new webpack.optimize.UglifyJsPlugin({
        /* ソースマップがある場合はここでも指定 */
        sourceMap: true,
        compress: {
          warnings: false
        },
      }),
      /* CSSを抽出する */
      new ExtractTextPlugin({
        filename: './css/app.bundle.css'
      }),
      /* ローダー用オプション ロードファイルの改行スペース省くだけ? ↓かどっちか */
      /*new webpack.LoaderOptionsPlugin({
        minimize: true,
      }),*/
      /* CSSの最適化 */
      /*new OptimizeCSSPlugin({
        cssProcessorOptions: {
          safe: true,
        },
      }),*/
    ],
  }
  webpack(webpackBaseConfig, function (error, stats) {});
};

gulp.task('webpack.build', function () {
  webpackBuild('production');
});
gulp.task('webpack.dev', function () {
  webpackBuild('development');
});

ちょっと遅いのでやっぱりホットリロード神ですね(っ'ω'c)ෆ

.vueファイル

.vue ファイルの中にはコンポーネントの JavaScript コードと、テンプレートそしてテンプレートで使う CSS がまとめて書けます。HTML がそのまま書けるようになって良いですね。

このファイルを import や require で読み込んでそのまま components に登録します。

<template>
<div class="piyo">
    {{ text }}
</div>
</template>
<script>
module.exports = {
    data: function() {
        return {
            text: 'piyo',
        }
    }
}
</script>
<style>
.piyo { color: #ffbb00; }
</style>

Vue の開発もだいぶ捗りそうですね!

Vue と CMS と jQuery

ところで私のサイトは CMS に MODX を使っていて既に少しづつ Vue を取り入れています。

ゲット用のAPI を作って SPA にするか Pjax と組み合わせてみるか考えてますが、バックエンドの記事管理やデータ作成を MODX で行って、フロントは Vue.js でという感じにサイトを改良していく予定です。

とりあえず今まで何も考えずに jQuery で作っていた所はネイティブや Vue コンポーネントにしました。Vue は導入する場合全部作りなおさないとダメというわけじゃなくて、すこしづつ移行できるっていうのもいいですねー(๑'ᴗ'๑)

jQuery は jQuery で便利だし予め考えてページを作っておけば Vue との共存も問題なさそうなので、必要なページだけ読み込んでいく感じにしようかなーと思います。

Edited on 2017.03.24 Created on 2017.02.18 Vue.js JavaScript Webデザイン Gulp 開発環境