FORSMILE
EN
開発記事2016/01/28

gulpの使い方:Aureliaのgulpをベースに解説

Node.js,Express環境でAurelia.jsを動かしてみる--その4

ブログ一覧へ / Back to Blog

Node.js,Express環境でAurelia.jsを動かしてみる--その4

Node.js,Express環境でAurelia.jsを動かしてみる--その1

Node.js,Express環境でAurelia.jsを動かしてみる--その2

Node.js,Express環境でAurelia.jsを動かしてみる--その3

Aurelia-Skeleton-Navigationではビルドツールにgulpを使用しています。

そしてBrowsersyncを使用してファイル変更を即時ブラウザに反映できるように環境が構築されています。

⇒参考https://www.browsersync.io/

gulpになじみにがある方は良いですがわからないとつまづくことも多いと思い、実際にAurelia.jsで使われているgulpから紐解いてみようと思います。

gulpfile.jsについて

gulpの基本的な設定はgulpfile.jsで行います。Aurelia.jsのgulpfile.jsをみてみると下記のようになっています。

text
require('require-dir')('build/tasks');

require-dirというNodeのhelperを使ってbuild/tasksフォルダの中身を参照しています。

package.jsonを見るとdevDependenciesに記載されています。

通常はここでtask等を設定したりしますが、管理しやすく分離して使っているようです。

まずはgulp watchで実行されるwatch.jsを見てみます。

javascript
var gulp = require('gulp');
var paths = require('../paths');
var browserSync = require('browser-sync');

// outputs changes to files to the console
function reportChange(event) {
  console.log('File ' + event.path + ' was ' + event.type + ', running tasks...');
}

// this task wil watch for changes
// to js, html, and css files and call the
// reportChange method. Also, by depending on the
// serve task, it will instantiate a browserSync session
gulp.task('watch', ['serve'], function() {
  gulp.watch(paths.source, ['build-system', browserSync.reload]).on('change', reportChange);
  gulp.watch(paths.html, ['build-html', browserSync.reload]).on('change', reportChange);
  gulp.watch(paths.css, ['build-css']).on('change', reportChange);
  gulp.watch(paths.style, function() {
    return gulp.src(paths.style)
      .pipe(browserSync.stream());
  }).on('change', reportChange);
});

gulpはnode.jsベースですので必要なプラグインやモジュールをrequireで指定します。

paths.jsにnodeのモジュールとして各pathが設定されています。

ファイルの変更とブラウザでの更新を同期させるパッケージです。ソースの変更が即時ブラウザに反映されるので作業効率が良くなります。

gulp.taskについて

text
gulp.task('watch', ['a', 'b']);

仮に上記のように設定されていた場合、watch,a,bという三つのタスクが実行されます。

watch.jsの場合はserveタスクが実行されたのちwatchされる。

単純に順番だけ定義したい場合はrun-sequenceパッケージを使うと楽。build.jsで実際に使われているので後述します。

gulp.watchについて

text
gulp.watch(paths.source, ['build-system', browserSync.reload]).on('change', reportChange);

上記を解説すると、paths.sourceにある対象のファイルが変更されたら、build-systemタスクとbrowserSync.reloadを実行する。その際に、reportChange関数を呼び出します。

前述しましたがpathsはpaths.jsにて定義されています。

serveタスクについて

watchタスクが実行される前に実行されるserveタスクについてみてみます。

javascript
var gulp = require('gulp');
var browserSync = require('browser-sync');

// this task utilizes the browsersync plugin
// to create a dev server instance
// at http://localhost:9000
gulp.task('serve', ['build'], function(done) {
  browserSync({
    online: false,
    open: false,
    port: 9000,
    server: {
      baseDir: ['.'],
      middleware: function(req, res, next) {
        res.setHeader('Access-Control-Allow-Origin', '*');
        next();
      }
    }
  }, done);
});

今度はserveが実行される前にbuildタスクが実行されています。

buildタスクが終了すると、browserSyncを使用してローカルサーバが立ち上がる仕組みになっています。

上記設定の場合は http://localhost:9000 にアクセスすることが可能になります。

browserSyncに関しては次回もう少し掘り下げて説明します。

Access-Control-Allow-Origin

ブラウザのアドレスバーに表示されているドメインとは別のドメインへデータを取得しにいくときに同一生成元ポリシー(クロスドメイン制約)に引っかからないようにするためのものです。

buildタスクについて

javascript
var gulp = require('gulp');
var runSequence = require('run-sequence');
var changed = require('gulp-changed');
var plumber = require('gulp-plumber');
var to5 = require('gulp-babel');
var sourcemaps = require('gulp-sourcemaps');
var paths = require('../paths');
var compilerOptions = require('../babel-options');
var assign = Object.assign || require('object.assign');
var notify = require("gulp-notify");
var browserSync = require('browser-sync');

// transpiles changed es6 files to SystemJS format
// the plumber() call prevents 'pipe breaking' caused
// by errors from other gulp plugins
// https://www.npmjs.com/package/gulp-plumber
gulp.task('build-system', function() {
  return gulp.src(paths.source)
    .pipe(plumber({errorHandler: notify.onError('Error: <%= error.message %>')}))
    .pipe(changed(paths.output, {extension: '.js'}))
    .pipe(sourcemaps.init({loadMaps: true}))
    .pipe(to5(assign({}, compilerOptions, {modules: 'system'})))
    .pipe(sourcemaps.write({includeContent: true}))
    .pipe(gulp.dest(paths.output));
});

// copies changed html files to the output directory
gulp.task('build-html', function() {
  return gulp.src(paths.html)
    .pipe(changed(paths.output, {extension: '.html'}))
    .pipe(gulp.dest(paths.output));
});

// copies changed css files to the output directory
gulp.task('build-css', function() {
  return gulp.src(paths.css)
    .pipe(changed(paths.output, {extension: '.css'}))
    .pipe(gulp.dest(paths.output))
    .pipe(browserSync.stream());
});

// this task calls the clean task (located
// in ./clean.js), then runs the build-system
// and build-html tasks in parallel
// https://www.npmjs.com/package/gulp-run-sequence
gulp.task('build', function(callback) {
  return runSequence(
    'clean',
    ['build-system', 'build-html', 'build-css'],
    callback
  );
});

パッケージとモジュールについて

watchでファイル変更を監視している際にエラーなどで監視が終了しないようにする

plumberとあわせて使用されている。タスク終了しない代わりに通知を出している

SourceMapとは、コンパイルや圧縮されて難読化されたコードがオリジナルファイルの何行目になるのか、マッピング情報が書かれたファイル。ここではbabelで生成されたものに対してSoucemapを作成している

babelのoptionを指定したモジュールを読み込んでいる

gulp-babelを読み込むタイミングで使われている。複数のオブジェクトを一つのオブジェクトにまとめている

build.jsないのbuild-systemタスクをみてみます。

javascript
gulp.task('build-system', function() {
  return gulp.src(paths.source)
    .pipe(plumber({errorHandler: notify.onError('Error: <%= error.message %>')}))
    .pipe(changed(paths.output, {extension: '.js'}))
    .pipe(sourcemaps.init({loadMaps: true}))
    .pipe(to5(assign({}, compilerOptions, {modules: 'system'})))
    .pipe(sourcemaps.write({includeContent: true}))
    .pipe(gulp.dest(paths.output));
});

処理するソースはpaths.sourceでここではsrc/以下のjsファイルになります。(paths.jsで指定されている)

serveタスクから呼び出されているbuildタスクが実行されるとrunSequenceにより実行順が定義されclean,実行の後、build-system, build-html, build-css 左記三つのタスクが並列で実行されています。

javascript
gulp.task('build', function(callback) {
  return runSequence(
    'clean',
    ['build-system', 'build-html', 'build-css'],
    callback
  );
});

gulp watchが実行されたときに行われるタスクを追ってきましたがBrowserSyncと連動してなかなか良い環境が構築されていると思います。

📦
Amazon で関連書籍・ツールを検索
Web開発 プログラミング 入門
Amazonで探す →(アソシエイトリンク)