Gulp + Webpack + Babel + Vue.js で作るWordPressテーマ開発環境


動機

  • WrodPress(REST API)改修案件でトランスパイルされたJSと格闘
  • JQueryそろそろもういいんじゃねぇの? → Vue.js使ってみよ
  • 運用フェーズでのJavascriptの見通し

JQueryの、このライブラリ使いたい!どうしても!(そうしたら工数圧縮できるのに...)
って人のために Vue.js + JQuery の共存も考慮しています。

フロントエンド開発環境界隈

browserify から Webpack の台頭があったようで
正直どっちでもいいけど多数派を選択したいところ

概念

2017年くらい

Gulp > Webpack > babel > Vue
——————————————————
 - stream   (webpack-stream) 
        -loader     (babel-loader) (vue-loader)
                                  + present

2015年くらい

Gulp > browserify > babel > Vue 
——————————————————
 - stream    (vinyl-source-stream)
                - ~ify          (babelify)  (vueify)
                                  + present

Gulp + Webpack + Babelの概念に関してはこちらが秀逸
参考:gulpとbabelとwebpackというフロント開発3銃士

Gulp先輩 > Webpack先輩 > Babel君という理解でいいかと思います。

チュートリアルに従って、npm i -Dしていくとなんだかわけの分からないものを何も考えずにインストールしていることが多いので、モジュール類も含めて概念をまとめてみました。

Gulp先輩の下に webpackbrowserify を従えるときは、 -streamモジュールが必要で、
webpackbrowserify の下に babel を従えるときは、 〜-loader〜 ~ify モジュールが必要という理解でいきます。

タスクを渡すときはこのモジュールを介して渡していきます。
Gulpモジュールの親玉に plumber が居るって感じでしょうか。

そのほかの便利モジュール

  • vue-template-compiler ( .vue を使えるようにする)
  • eslint (コードチェック) : eslint-for-vue

いいわけ

※2018年初頭に「babel / vue 」キーワードでGoogleで検索して把握した概要です。
※Sassはそもそもcssをjsに統合する必要性がわからなかったので、node-sassに任せておきます。
※執筆時点でvueの構文(便利さ)は理解していません。
※全体をVue,jsで組むなら、vue-cliが始めやすいらしいですよ。

各種設定ファイル

ディレクトリ構成

大事なのは設定ファイルの位置とコンパイラを動かして、出力されたディストリビューションファイルの位置関係かと思います。

別記事でDockerをつかったWordPressテーマ開発環境を整えたので、それに従っています。VCCWや mampp / xampp 環境の場合は出力ファイルの位置が変わるかと思うので設定ファイルのパスを読み替えてください。

Dir構成
package.json ← いまからつくる
gulpfile.js ← いまからつくる
--- ここから Docker ---
public (Wordpressディレクトリ)
db-data / wordpress-dump-xxxxxxx.sql
docker-compose.yml

初期設定

package.json (node)

最初につくるときは npm initで、空の package.json ができあがります。

$ npm init
Dir構成
package.json ← 出来た
--- ここから Docker ---
public (Wordpressディレクトリ)
db-data / wordpress-dump-xxxxxxx.sql
docker-compose.yml

npm i -D XXX していくとプロジェクトごとのpackage.jsonが仕上がっていきます。
(iinstall-D--save-dev の略)

$ npm i -D gulp gulp-autoprefixer gulp-clean-css gulp-notify gulp-plumber gulp-sass
$ npm i -D webpack webpack-stream
$ npm i -D babel-core babel-loader babel-preset-env
$ npm i --save vue
$ npm i -D vue-loader vue-template-compiler

わかりやすく行分けしていますが、もちろんワンライナーでもインストールできます。
gulpのもろもろは個人的な趣味です。

npm WARN [email protected] requires a peer of css-loader@* but none is installed. You must install peer dependencies yourself.

vue-loaderいれるとcss-loaderも入れろって出てきます。
素直にいれとこう

$ npm i -D css-loader

package.json があるディレクトリでnpm installまたはnpm iを実行するとnode_moduleがインストールされます。
チームで開発するときは、プロジェクトディレクトリのソースを共有して、git pullしてnpm installしてくださいねって言うだけでいい。
(GulpなどはCLIで実行することになるので、グローバルインストールnpm i -g gulpが必要ですね)

Vueテンプレート(.Vue)style-cssを含むをコンパイルできるようにする

$ npm i -D vue-style-loader

出来上がったpackage.jsonがこんな感じ

package.json
{
  "name": "example",
  "version": "1.0.0",
  "description": "######",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "babel-core": "^6.26.0",
    "babel-loader": "^7.1.2",
    "babel-preset-env": "^1.6.1",
    "css-loader": "^0.28.9",
    "gulp": "^3.9.1",
    "gulp-autoprefixer": "^4.1.0",
    "gulp-clean-css": "^3.9.2",
    "gulp-notify": "^3.2.0",
    "gulp-plumber": "^1.2.0",
    "gulp-sass": "^3.1.0",
    "jquery": "^3.3.1",
    "vue-loader": "^13.7.0",
    "vue-template-compiler": "^2.5.13",
    "webpack": "^3.10.0",
    "webpack-stream": "^4.0.0",
    "vue-style-loader": "^4.1.2"
  },
  "dependencies": {
    "vue": "^2.5.13"
  }
}

gulpfile.js

varじゃなくて、constって書けるんですね!
webpackは素通りしてきたので、webpack.configは書かない(gulpfileにまとめる)方向でひとつお願いします。

Dir構成
package.json ← Done
gulpfile.js ← いまからつくる
--- ここから Docker ---
public (Wordpressディレクトリ)
db-data / wordpress-dump-xxxxxxx.sql
docker-compose.yml

注) example はテーマ(テーマディレクトリ)名とします。
注) paths は各々読み替えて!

gulpfille.js
const gulp = require('gulp'),
    plumber = require("gulp-plumber"),
    sass = require('gulp-sass'),
    cleancss = require('gulp-clean-css'),
    autoprefixer = require('gulp-autoprefixer'),
    notify = require('gulp-notify'),
    webpack = require('webpack'), // Let's use webpack.DefinePlugin
    webpackStream = require('webpack-stream'), // Let's use webpack3
    VueLoaderPlugin = require('vue-loader'); // vue-loader

const paths = {
    "url":"localhost:8802",
    "css": "./public/wp/wp-content/themes/example/assets/css/",
    "scss": "./public/wp/wp-content/themes/example/assets/scss/**/*.scss",
    "entry": "./public/wp/wp-content/themes/example/assets/js/src/main.js",
    "js": "./public/wp/wp-content/themes/example/assets/js/",
}

//Sass
gulp.task('sass',function(){
    return gulp.src(paths.scss)
    .pipe(plumber())
    .pipe(sass({outputStyle: 'expanded'}))
    .pipe(cleancss({debug: true}, function(details) {
            console.log(details.name + ': ' + details.stats.originalSize + ' > ' +  + details.stats.minifiedSize);
    }))
    .pipe(autoprefixer({
        browsers: ["last 2 versions", "ie >= 9", "Android >= 4","ios_saf >= 8"],
        cascade: false
    }))
    .pipe(gulp.dest(paths.css))
    .pipe(notify("Sass Compile Success!"));
});

//Webpack JS bundle
gulp.task('bundle', function(){
    return gulp.src( [ paths.entry ] )
        .pipe(plumber())
        .pipe(webpackStream({
            // watch: true, // webpack の watch ではなく gulp の watch を使う
            output: {
                filename: 'build/bundle.js',
            },
            module: {
                rules: [
                    {
                      test: /\.vue$/,
                       loader: 'vue-loader',
                       options: {
                           options: {
                                presets: [
                                    'es2015',
                                         {
                                         targets: {
                                             browsers: ['last 2 versions', 'safari 7', 'edge 14'],
                                         },
                                    },
                                ],
                            },
                        // other vue-loader options go here
                        },
                    },
                    {
                        test: /\.js$/,
                        resourceQuery: paths.js + 'src/',
                        loader: 'babel-loader',
                        options: {
                                presets: [
                                    'es2015',
                                         {
                                         targets: {
                                             browsers: ['last 2 versions', 'safari 7', 'edge 14'],
                                         },
                                    },
                                ],
                        }
                    },
                    {
                        test: /\.css$/,
                        oneOf: [
                            {
                                resourceQuery: /module/,
                                use: [
                                    'vue-style-loader',
                                    {
                                        loader: 'css-loader',
                                        options: {
                                            modules: true,
                                            localIdentName: '[local]_[hash:base64:5]',
                                        },
                                    },
                                ],
                            },
                            // this matches plain `<style>` or `<style scoped>`
                            {
                                use: ['vue-style-loader', 'css-loader'],
                            },
                        ],
                    },
                ],
            },
            resolve: {
                extensions: ['.js', '.vue'],
                modules: [
                    "node_modules"
                ],
                alias: {
                }
            },
            //環境によってビルドする内容を分ける
            plugins: [
                new webpack.DefinePlugin({
                    'process.env': {
                        NODE_ENV: '"production"'
                    }
                }),
                new webpack.optimize.UglifyJsPlugin(),
                new webpack.optimize.DedupePlugin(),  // ライブラリ間で依存しているモジュールが重複している場合、二重に読み込まないようにする
                new webpack.optimize.AggressiveMergingPlugin(),  //ファイルを細かく分析し、まとめられるところはできるだけまとめてコードを圧縮する
                // JQuery / JQueryライブラリのための定義(Jquery絶対使わないってプロジェクトのときは消去)
                new webpack.ProvidePlugin({
                    jQuery: "jquery",
                    $: "jquery",
                    jquery: "jquery"
                }),
                // vueコンポーネント
                new VueLoaderPlugin(),
            ]
        }, null, function(err, stats) {
            /* Use stats to do more things if needed */
            if (stats.compilation.errors.length) {
                notify.onError({
                    title: 'Webpack error',
                    message: stats.compilation.errors[0].error,
                    sound: 'Frog',
                });
            }
        }))
        .pipe(gulp.dest( paths.js ))
        .pipe(notify("Bundle JS Success!"));
})

gulp.task('default', ['sass','bundle'], function () {
    gulp.watch(paths.scss, ['sass']);
    gulp.watch( [paths.entry], ['bundle']);
});

チームで開発するときは、gulp してくださいねって言うだけでいい。

WordPress でVue-JSを使う

WordPressテーマディレクトリの function.php に以下を追加
header直書きよりこちらがおすすめ

function.php
wp_enqueue_script( 'vue-js', 'https://cdn.jsdelivr.net/npm/vue', [], 'latest', true );
wp_enqueue_script( 'example-bundle', get_theme_file_uri( '/assets/js/build/bundle.js' ), array( 'jquery’, 'vue-js' ), '1.0', true );

今後の展望

  • .env でプロジェクトごとの設定を管理

最近書いた記事

Dockerで作るWordPressテーマローカル開発環境
Gulp + Webpack(+Babel)でシンプルJQuery構成
Gulp + yarn シンプルJQuery構成

参考にさせていただいたサイト(多謝)

gulpとbabelとwebpackというフロント開発3銃士
Vue.js 単一ファイルコンポーネントを使って開発環境を強化する
Vue.js 開発環境を手作りしてみた手順(自分メモ)
GulpでVue+SASSの開発環境を構築する

修正履歴

2018.02.05 - vue-template-compiler vue-style-loader をインストール、Vueコンポーネント(.vue)とその中のcssをコンパイルできるように修正