読者です 読者をやめる 読者になる 読者になる

tanaka's Programming Memo

プログラミングについてのメモ。

generator-react-gulp-browserifyに含まれているgulpfile.jsを読む

JavaScript Yeoman 勉強メモ gulp

gulpの動作を勉強するために、やりたい処理を実現しているyeomanのrandylien/generator-react-gulp-browserify · GitHubに含まれているgulpfile.jsの中身を読んでみました。

'use strict';
  • strictモードにして、JavaScriptの動作を厳格にします。
var gulp = require('gulp');
var del = require('del');
var path = require('path');
// Load plugins
var $ = require('gulp-load-plugins')();
var browserify = require('browserify');
var watchify = require('watchify');
var source = require('vinyl-source-stream'),
    sourceFile = './app/scripts/app.js',

    destFolder = './dist/scripts',
    destFileName = 'app.js';
  • ファイルやフォルダーのパスを定義しています。
  • sourceFile
  • destFolder
    • ビルド後のファイルを出力する先のフォルダー
  • destFileName
var browserSync = require('browser-sync');
var reload = browserSync.reload;
  • browser-sync
    • ローカルHTTPサーバーを立てることと、ライブリロードするためのプラグイン
  • reload
    • リロードをするための関数
// Styles
gulp.task('styles', ['sass'  ]);
  • stylesタスクを定義します。
  • このタスクが呼ばれたら、sassタスクを実行します。
gulp.task('sass', function() {
  • sassタスクを定義します。stylesタスクを実行すると呼ばれます。
    return gulp.src(['app/styles/**/*.scss', 'app/styles/**/*.css'])
  • gulp.src()で、処理するファイルリストを作ります。app/stylesフォルダー下の全ての子フォルダーにある*.scssファイルと、*.cssファイルに、この後に続くpipe()を処理します。
        .pipe($.rubySass({
            style: 'expanded',
            precision: 10,
            loadPath: ['app/bower_components']
        }))
  • sassを処理(今回は知りたいことと違うので詳細省略)
        .pipe($.autoprefixer('last 1 version'))
  • 最後の1バージョンをバックアップしておくと思われる
        .pipe(gulp.dest('dist/styles'))
        .pipe($.size());
});
  • ファイルサイズを表示
gulp.task('stylus', function() {
    return gulp.src(['app/styles/**/*.styl'])
        .pipe($.stylus())
        .pipe($.autoprefixer('last 1 version'))
        .pipe(gulp.dest('dist/styles'))
        .pipe($.size());
});
  • stylusを使ったcssの生成をします。やっていることはsassと同じです。
var bundler = watchify(browserify({
    entries: [sourceFile],
    debug: true,
    insertGlobals: true,
    cache: {},
    packageCache: {},
    fullPaths: true
}));
  • watchifyを適用させた上で、browserifyを実行するためのインスタンスを生成しています。
    • entriesで基礎となるjavascriptファイルを指定しています。このプロジェクトでは、./app/scripts/app.jsです。
    • debug: trueで、mapファイルがあれば、対応させます。
    • insertGlobals: trueで、検索をせず、processやglobal、__filename、__dirnameに定義を常に追加します。サイズが大きくなる代わりに、処理が速くなります。
    • chache,packageCacheはなんらかのキャッシュの設定のようです。
    • fullPathsで、moduleのidを数値に変換しないようにしています。
  • 参考URL:browserify
bundler.on('update', rebundle);
  • browserifyが対象としているファイルに変更があった場合、rebundle関数が実行されるように登録します。
  • 参考URL:watchify
bundler.on('log', $.util.log);
  • フォームのメッセージがあると起動して、$.util.logを使って、watchifyからのログを画面に出力します。
function rebundle() {
  • watchifyで更新を確認したら実行するハンドラです。
    return bundler.bundle()
  • bundlerで設定したbrowserifyの設定をビルドします。
        // log errors if they happen
        .on('error', $.util.log.bind($.util, 'Browserify Error'))
  • エラーが発生していたら、$.util.logを使って、$.utilをthisとして、Browserify Errorと出力します。
        .pipe(source(destFileName))
  • ビルド結果を、app.jsとして、vinyl-source-streamに変換します。
        .pipe(gulp.dest(destFolder))
  • 変換結果をdestFolderに出力します。
        .on('end', function() {
            reload();
        });
}
  • 処理が終了したら、ライブリロードします。
// Scripts
gulp.task('scripts', rebundle);
  • scriptsタスクとして、rebundleを登録します。
gulp.task('buildScripts', function() {
  • buildScriptsタスクを定義します。最初のビルド用のため、watchifyを利用せずにビルドします。
    return browserify(sourceFile)
  • browserifyに、対象をsourceFileで指定します。
        .bundle()
  • browserifyでビルドします。
        .pipe(source(destFileName))
  • 出力先の名前をdestFileName(app.js)とします。
        .pipe(gulp.dest('dist/scripts'));
});
  • dist/scriptsフォルダーに出力します。
    gulp.task('jade', function() {
        return gulp.src('app/template/*.jade')
            .pipe($.jade({
                pretty: true
            }))
            .pipe(gulp.dest('dist'));
    })
  • jadeとは、express.jsなどで採用されているjavascriptのテンプレートエンジンだそうです。
  • 今回はテーマ外なので詳しく触れず。
  • *.jadeを変換して、distフォルダーに保存しています。
  • 参考URL:Jade について。
// HTML
gulp.task('html', function() {
  • htmlタスクを作成しています。
    return gulp.src('app/*.html')
  • appフォルダー内の*.htmlに以下の処理を逐一実行します。
        .pipe($.useref())
  • gulp-userefは、grunt-userefのgulp版のプラグインです。
  • minifyや変換などに対応するためのHTML内の記述をパースするようです。
  • useref()で、変換を実行しています。
        .pipe(gulp.dest('dist'))
        .pipe($.size());
});
  • 変換後のHTMLファイルをdistフォルダーにコピーして、ファイルサイズを出力します。
// Images
gulp.task('images', function() {
    return gulp.src('app/images/**/*')
        .pipe($.cache($.imagemin({
            optimizationLevel: 3,
            progressive: true,
            interlaced: true
        })))
        .pipe(gulp.dest('dist/images'))
        .pipe($.size());
});

// Fonts
gulp.task('fonts', function() {
    return gulp.src(require('main-bower-files')({
            filter: '**/*.{eot,svg,ttf,woff,woff2}'
        }).concat('app/fonts/**/*'))
        .pipe(gulp.dest('dist/fonts'));
});
  • 画像とフォントを処理して、distフォルダーの指定の場所に保存しています。
// Clean
gulp.task('clean', function(cb) {
    $.cache.clearAll();
    cb(del.sync(['dist/styles', 'dist/scripts', 'dist/images']));
});
  • cleanタスクを定義しています。
  • キャッシュ、各distフォルダー内を削除しています。
// Bundle
gulp.task('bundle', ['styles', 'scripts', 'bower'], function() {
  • bundleタスクを定義しています。
  • 事前に、styles(SASSのビルド)、scripts(jsのwatchify)、bower(appフォルダー内のbowerコンポーネントをdistフォルダーにコピー)タスクを実行します。
    return gulp.src('./app/*.html')
  • appフォルダー内のhtmlに以下の処理を実行します。
        .pipe($.useref.assets())
        .pipe($.useref.restore())
        .pipe($.useref())
  • HTMLのパースを実行します。
        .pipe(gulp.dest('dist'));
});
  • distフォルダーにコピーします。
gulp.task('buildBundle', ['styles', 'buildScripts', 'bower'], function() {
  • buildBundleタスクを定義します。
  • 事前に、styles(sassのビルド)、buildScripts(browserifyの初期ビルド)、bowerのコピーを実施します。
    return gulp.src('./app/*.html')
        .pipe($.useref.assets())
        .pipe($.useref.restore())
        .pipe($.useref())
        .pipe(gulp.dest('dist'));
});
  • appフォルダー内のhtmlファイルを変換して、distにコピーします。
// Bower helper
gulp.task('bower', function() {
    gulp.src('app/bower_components/**/*.js', {
            base: 'app/bower_components'
        })
        .pipe(gulp.dest('dist/bower_components/'));

});
  • appフォルダー内のbowerコンポーネント内のjsファイルを、distフォルダーにコピーします。
gulp.task('json', function() {
    gulp.src('app/scripts/json/**/*.json', {
            base: 'app/scripts'
        })
        .pipe(gulp.dest('dist/scripts/'));
});
  • jsonタスクを定義します。
  • appフォルダー内のjsonフォルダーの*.jsonファイルを、distフォルダーにコピーします。
// Robots.txt and favicon.ico
gulp.task('extras', function() {
    return gulp.src(['app/*.txt', 'app/*.ico'])
        .pipe(gulp.dest('dist/'))
        .pipe($.size());
});
  • extrasタスクを定義します。
  • app/*.txtと、app/*.icoファイルをdistフォルダーにコピーして、ファイルサイズを表示します。
// Watch
gulp.task('watch', ['html', 'fonts', 'bundle'], function() {
  • watchタスクを作成します。
  • 事前に、htmlの処理、fontsのコピー、javascriptの差分ビルドを実行します。
    browserSync({
        notify: false,
        logPrefix: 'BS',
        // Run as an https by uncommenting 'https: true'
        // Note: this uses an unsigned certificate which on first access
        //       will present a certificate warning in the browser.
        // https: true,
        server: ['dist', 'app']
    });
  • ローカルのhttpサーバを起動します。
  • サーバーはdistフォルダーとappフォルダーに立ち上げます。
    // Watch .json files
    gulp.watch('app/scripts/**/*.json', ['json']);
  • appフォルダー内の*.jsonファイルに変更があったら、jsonタスクを実行します。
    // Watch .html files
    gulp.watch('app/*.html', ['html']);
  • appフォルダー内の*.htmlファイルが変更されたら、htmlタスクを実行します。
    gulp.watch(['app/styles/**/*.scss', 'app/styles/**/*.css'], ['styles', reload]);
  • app/stylesフォルダー内のscssやcssファイルが変更したら、stylesとreloadタスクを実行します。
        // Watch .jade files
        gulp.watch('app/template/**/*.jade', ['jade', 'html', reload]);
  • *.jadeファイルに変更があったら、jade、htmlタスクを実行して、ライブリロードします。
    // Watch image files
    gulp.watch('app/images/**/*', reload);
});
  • imagesフォルダーの中身が更新されたら、ライブリロードします。
// Build
gulp.task('build', ['html', 'buildBundle', 'images', 'fonts', 'extras'], function() {
  • buildタスクを定義します。
  • 事前に、htmlの処理、browserifyの初期ビルド、imagesやfonts、extrasのコピーを実行します。
    gulp.src('dist/scripts/app.js')
  • dist/scripts/app.jsファイルに以下を適用します。
        .pipe($.uglify())
  • javascriptの圧縮タスクを実行します。
        .pipe($.stripDebug())
        .pipe(gulp.dest('dist/scripts'));
});
  • dist/scriptsに結果を出力します。
// Default task
gulp.task('default', ['clean', 'build'  , 'jest'  ]);
  • ターミナルでgulpを実行した時の動作を定義しています。
  • キャッシュやdistフォルダー内を削除します。
  • buildタスクを実行して、プロジェクトを再生成して、圧縮やデバッグコードの削除を実行します。
  • jestはテストを実施するプラグインです。最後にテストを実行します。


以上です。