WordPress等のCMSがjQuery等を出力するとき、browserifyで上手いことやる。

最近、jsでrequireが無いと生きれない身体になってしまいました。

CoffeeScriptから卒業して、ES6でコードを書くようにもしています。ES6のClass構文とかアロー関数が無いと人生辛くなってきました。

そんなわけで自分はbrowserifyを使ってコードを書いてます。requireを良い感じにコンパイルして1つのファイルにまとめてくれる奴です。

そんなときに結構困るのがwp_head()や、wp_footer()からscriptタグでjQueryunderscore.jsBackbone.js等の有名処のライブラリが出力される場合があることです。

functions.phpで無理矢理消しても良いのですがそれは筋が悪そうなので、browserify-shimを使って指定されたライブラリはグローバル変数のものを使うようにします。

そのコードがこんな感じ。

gist: https://gist.github.com/torounit/0da591b62d03187b4641

package.json

{
  "browserify-shim": {
    "jquery": "global:jQuery",
    "underscore": "global:_",
    "backbone": "global:Backbone"
  },
  "devDependencies": {
    "babelify": "^6.1.3",
    "browserify": "^11.0.0",
    "browserify-shim": "^3.8.10",
    "debowerify": "^1.3.1",
    "gulp": "^3.9.0",
    "gulp-notify": "^2.2.0",
    "vinyl-buffer": "^1.0.0",
    "vinyl-source-stream": "^1.1.0",
    "watchify": "^3.3.0"
  },
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "Toro_Unit",
  "license": "ISC"
}

gulpfile.js

'use strict';

// ==================================
//
// Config.
//
// ==================================

var config = {
    browserify: {
        bundleOption: {
            cache: {}, packageCache: {}, fullPaths: false, //for watchfy.
            debug: true,
            entries: './src/scripts/app.js',
            extensions: ['js', 'jsx'],
        },
        dest: './dist/scripts/',
        filename: 'app.js'

    }
}

// ==================================
//
// Load modules.
//
// ==================================

var source = require('vinyl-source-stream');
var browserify = require('browserify');
var watchify = require('watchify');
var gulp = require('gulp');
var notify = require("gulp-notify");

var handleErrors = function() {
    var args = Array.prototype.slice.call(arguments);
    notify.onError({
        title: "Compile Error",
        message: "<%= error.message %>"
    }).apply(this, args);
    this.emit('end');
};

// ==================================
//
// Compile JavaScripts.
//
// ==================================

gulp.task('setWatch', function () {
    global.isWatching = true;
});

gulp.task('browserify', function () {

    var b = browserify(config.browserify.bundleOption)
        .transform('babelify')
        .transform("browserify-shim")
        .transform("debowerify");

    var bundle = function () {
        b.bundle().on('error', handleErrors)
            .pipe(source(config.browserify.filename))
            .pipe(gulp.dest(config.browserify.dest));
    };
    if (global.isWatching) {
        var bundler = watchify(b);
        bundler.on('update', bundle);
    }
    bundle();
});

gulp.task('watchify', ['setWatch', 'browserify']);

タスク

$ gulp browserify //コンパイル
$ gulp watchify //ファイルの変更を監視して自動コンパイル

といった格好になります。

browserify-shim

browserifyには、transformというAPIがありまして、ここにプラグインを突っ込むことが出来ます。

アプリケーションコード上のJSから呼び出せるのは通常、node_modulesにインストールされているものか、ファイル名で指定されたJSのみですが、require(‘jquery’) のようなコードを書いたときに、node_modulesではなく、グローバル変数のjQueryを呼んでくることが出来るようになります。

package.jsonにbrowserify-shimという項目を作ってこんな感じで指定すれば動作します。

{
  "browserify-shim": {
    "jquery": "global:jQuery",
    "underscore": "global:_",
    "backbone": "global:Backbone"
  }
}

debowerify

debowerifyは、bowerでインストールしたライブラリをrequireやimportできるようにするプラグインです。

最近オワコンと言われているbowerですが、jQueryプラグインなどをnpmでインストールして持ってくると、そこからnode_modules内のjqueryを取ってきてしまうと言う問題があります。shimの方の設定が悪いのかどうなのか解らないのですが、そんなわけでその手のものは仕方ないのでbowerで持ってきてrequire(import)します。

npmだけで管理はしたいのでどうにかしたいところです。最悪、jQueryプラグインも普通にscriptタグで読み込ませるコトもたまにやります。

 

まとめ

とりあえずこれで、ライブラリの多重インストールを避けつつインストールが出来ます。後はテーマ側で

$js_path = get_template_directory_uri() . 'dist/scripts/app.js';
wp_enqueue_script( 'app', $js_path, array( 'underscore', 'jquery' ), '1.0.0', true );

とかやればとりあえずは終了です。

まぁ、WordPressのunderscore.jsとかBackbone.jsバージョンが古い問題とかもあるんですけどね。。。