gulpで各ファイルの出力先をページベースに変更する方法

gulpを利用している場合、.js.scssなどを各フォルダに分けて管理することが多いかと思います。

src/

  js/
    about/
      index.js
    contact/
      index.js
    common/
      common.js
    index.js

  scss/
    common/
      reset.scss
    about/
      index.scss
    contact/
      index.scss
    index.scss

  images/
    about/
      main.png
      ...
    contact/
      main.png
      ...
    common/
      ...

  jade/
    components/
      _layout.jade
    about/
      index.jade
    contact/
      index.jade

でも、出力するときは各階層にjs、css、ルートにindex.htmlって置きたい時あると思うんですね。

public/

  index.html
    js/
    css/
    images/

  about/
    index.html
    js/
    css/
    images/

  contact/
    index.html
    js/
    css/
    images/

  common/
    js/
    css/
    images/

このプロジェクトごとにファイルを分割するという方法を探っていた結果、うまく行った方法を書こうと思います。

gulp-renameでディレクトリパスを書き換える

.minなどの接尾辞をつけるときやファイル結合後のファイル名を変えるときによく使うgulp-renameですが、実は出力先のディレクトリ名もいじることができます。

これを使用してページベースのファイル構成に変更していきます。

パスを見てみる

今回は画像圧縮のタスクを例に書いていきます。
まずはgulp-renameのpathがどんな感じになっているのかをみましょー

今回使用するファイルは以下のように配置されています。

src/
  images/
    facebook-ogpsd.png
    2014-06-19.jpg
  about/
    odaji-ni.png

gulpfileはこんな感じで。


import gulp from 'gulp'
import rename from 'gulp-rename'

const config = {
  src: 'src',
  dest: 'public'
}

// imagemin
gulp.task('imagemin', () => {
  return gulp.src(`${config.src}/images/**/*.{png,jpg,jpeg,gif}`)
    .pipe(rename(function(path){
      console.log(path);
    }))
    .pipe(gulp.dest(`${config.dest}/images`));
});

gulpのタスクを行ってみます。

$ gulp imagemin
  Requiring external module babel-register
  Using gulpfile ~/Documents/private/websites/gulp-setting/gulpfile.babel.js
  Starting 'imagemin'...
  { dirname: '.', basename: 'facebook-ogpsd', extname: '.png' }
  { dirname: '.', basename: '2014-06-19', extname: '.jpg' }
  { dirname: 'about', basename: 'odaji-ni', extname: '.png' }
  Finished 'imagemin' after 46 ms

出力はこんな構造になっていました。

public/
  images/
    facebook-ogpsd.png
    2014-06-19.jpg
  about/
    odaji-ni.png

path.dirnameをいじればディレクトリを変更できそうですねー
ということでいじっていきましょう。

ディレクトリパスをいじる

public/images/about/odaji-ni.png → public/about/images/odaji-ni.png にしたいので、

  • path.dirnameに/imagesを追加
  • gulp.dest先をルートディレクトリ(public)に変更

しました。
gulp-renameの部分とgulp.destを以下のように修正します。


// imagemin
gulp.task('imagemin', () => {
  return gulp.src(`${config.src}/images/**/*.{png,jpg,jpeg,gif}`)
    .pipe(rename(function(path){
      path.dirname += '/images'; // imagesフォルダのパスを追加
      console.log(path);
    }))
    .pipe(gulp.dest(`${config.dest}`)); // ドキュメントルートからに変更
});

imageminタスクを実行してみましょう。

$ gulp imagemin
  Requiring external module babel-register
  Using gulpfile ~/Documents/private/websites/gulp-setting/gulpfile.babel.js
  Starting 'imagemin'...
  { dirname: './images',
    basename: 'facebook-ogpsd',
    extname: '.png' }
  { dirname: './images', basename: '2014-06-19', extname: '.jpg' }
  { dirname: 'about/images',
    basename: 'odaji-ni',
    extname: '.png' }
  Finished 'imagemin' after 46 ms

ディレクトリ構造はこうなっていました。

public/
  images/
    facebook-ogpsd.png
    2014-06-19.jpg
  about/
    images/
      odaji-ni.png

ちゃんとページベースになってますね!

画像圧縮タスクを書く

ということで画像圧縮タスクを作りました。
gulp-imageminを突っ込んでconsole.logを消しただけ。


import gulp from 'gulp';
import imagemin from 'gulp-imagemin';
import rename from 'gulp-rename';

// imagemin
gulp.task('imagemin', () => {
  return gulp.src(`${config.src}/images/**/*.{png,jpg,jpeg,gif}`)
    .pipe(imagemin())
    .pipe(rename(function(path){
      path.dirname += '/images';
    }))
    .pipe(gulp.dest(`${config.dest}`));
});

他のタスクだとどうすればいいの?

Sassやjsの場合も同様に可能です。

.scssなら

  • gulp.src: src/scss/**/*.scss
  • path.dirname: += '/css'

.jsなら

  • gulp.src: src/js/**/*.js
  • path.dirname: += '/js'

とすれば可能です。

htmlはドキュメントルートにそのまま入れるので、renameでのディレクトリ変更は必要ないかと思います。

  • gulp.src: src/html/**/*.html

最後に

「いや最初からページベースでフォルダ分けてればいいのでは」

…確かに。

  • BLOG
  • >
  • web
  • >
  • gulpで各ファイルの出力先をページベースに変更する方法