タグ: browserify-shim

  • 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バージョンが古い問題とかもあるんですけどね。。。