【mac用】npmでgulpを使い、ejsとscssの環境を作る

#前提
npmを使用するので下記3つがインストールされている前提で説明します。
・homebrew
・nodebrew
・node.js

インストール方法はこちら([参照](https://www.hirooooo-lab.com/entry/development/install-node))

##ディレクトリ構造

```plaintext:ディレクトリ構造
project
┃-ejs
┃　┃-この配下にejsファイルを作成していく
┃　┃-img(ここに画像を配置すると、自動的にhtml配下にもimgフォルダが生成され、軽量化された画像が出力されます)
┃　┃-includes
┃　┃　┃
┃　┃　meta.json(meta情報の一括管理。ここでの説明は割愛。)
┃-html
┃　┃-node_modules
┃　┃-gulpfile.js
┃　┃-package.json
┃　┃-gulp_install.command
┃　┃-css（ここにscssで変換されたcssファイルが格納されます）
┃-scss
┃　┃-この配下にscssファイルを作成していく
```

必要ファイルについては下記順次説明していきます。

##gulpで作成する制作環境に使うプラグイン
・browser-sync: ファイル変更の監視、ブラウザの自動リロード
・gulp-autoprefixer: ベンダープレフィックスの自動付与
・gulp-changed:変更ファイルのみ移動させる
・gulp-clean-css: cssの圧縮
・gulp-ejs: ejsのインストール
・gulp-imagemin:　画像軽量化
・gulp-notify: タスク実行中にエラーが出た際に通知を出す
・gulp-plumber: タスク実行中にエラーが出た際強制停止を防ぐ
・gulp-rename: ejsファイルをhtmlファイルに変換
・gulp-sass: sassのインストール
・gulp-sass-glob: sassのimportの簡略化
・gulp-svgmin: svgファイルの軽量化
・imagemin-gifsicle: gifファイルの軽量化
・imagemin-jpeg-recompress: jpegファイルの軽量化
・imagemin-pngquant: pngファイルの軽量化


#シェルスクリプトで一括インストール
いちいちターミナル開いてコマンドラインでインストールするのも手間なのでシェルスクリプト開いて一気にインストールしましょう。
てなわけでgulp_install.commandというファイルを作ります。

***※ソース管理を行い、複数人でファイルを共有して制作をしている場合等、
既にpackage.jsonやgulpfile.jsが作成された状態で
環境を構築する場合はコマンドラインでnpm installと実行するだけで問題ないです。
一回実行したあと、再度gulp_install.commandを実行すると再度インストールが始まります。
一度インストールしたプラグインが場合によっては最新のバージョンになり、
同じプロジェクトで共有しているファイルでもバージョンにズレがでてしまいますので要注意。***

```sh:gulp_install.command
#!/bin/sh

cd `dirname $0`
npm init -y
npm install gulp gulp-sass gulp-autoprefixer gulp-plumber gulp-notify gulp-clean-css gulp-sass-glob browser-sync gulp-ejs gulp-rename gulp-changed gulp-imagemin imagemin-gifsicle imagemin-jpeg-recompress imagemin-pngquant gulp-svgmin   --save-dev
npm run build
```
こちらのファイルをルートディレクトリに配置し、
gulp_install.commandをダブルクリックして開くだけで自動的に実行され、
node_modulesとpackage.jsonが生成されます。

#gulpfile.js（gulp設定ファイル）の作成

シェルスクリプトを実行できたら次はgulpfile.jsを作成します。


```js:gulpfile.js
// gulp core
var gulp = require('gulp');

var fs = require( 'fs' );

// sass compiler
var sass = require('gulp-sass');
// auto prifix
var autoprefixer = require('gulp-autoprefixer');
// error handling
var plumber = require('gulp-plumber');
// notify
var notify = require('gulp-notify');
// clean css
var cleanCSS = require('gulp-clean-css');
// server
var browser = require("browser-sync");

var ejs = require("gulp-ejs");

var rename = require("gulp-rename");

var sassGlob = require("gulp-sass-glob");

var changed  = require('gulp-changed');

var imagemin = require('gulp-imagemin');

var imageminJpg = require('imagemin-jpeg-recompress');

var imageminPng = require('imagemin-pngquant');

var imageminGif = require('imagemin-gifsicle');

var svgmin = require('gulp-svgmin');

var paths = {
  srcDir : '../ejs/**/',
  dstDir : './'
}
//task

gulp.task('server', function() {
  browser({
    server: {
      baseDir: "./"
    }
  });
});


gulp.task('sass', function() {
  gulp.src('../scss/**/*.scss')
    .pipe(sassGlob()) // Sassの@importにおけるglobを有効にする
    .pipe(plumber({
      errorHandler: notify.onError('Error: <%= error.message %>')
    }))
    .pipe(sass())
    .pipe(autoprefixer({
      browsers: ['last 2 version', 'iOS >= 8.1', 'Android >= 4.4','IE 10'],
            cascade: false
    }))
    .pipe(cleanCSS())
    .pipe(gulp.dest('css/'))
    .pipe(browser.reload({
      stream: true
    }));
});


gulp.task('ejs', function() {
  var json = JSON.parse(fs.readFileSync("../ejs/includes/meta.json","utf-8"));
  gulp.src(
      ["../ejs/**/*.ejs", '!' + "../ejs/**/_*.ejs"] //参照するディレクトリ、出力を除外するファイル
    )
    .pipe(plumber({
      errorHandler: notify.onError('Error: <%= error.message %>')
    }))
    .pipe(ejs({json:json}))
    .pipe(rename({
      extname: ".html"
    })) //拡張子をhtmlに
    .pipe(gulp.dest("./"));
});

//タスク部分
gulp.task('imagemin', function(){
    var srcGlob = paths.srcDir + '/*.+(jpg|jpeg|png|gif)'; //圧縮前画像ファイル
    var dstGlob = paths.dstDir;　//圧縮後画像ファイル
    gulp.src( srcGlob )
    .pipe(changed( dstGlob ))
    .pipe(imagemin([
        imageminPng(),
        imageminJpg(),
        imageminGif({
            interlaced: false,
            optimizationLevel: 3,
            colors:180
        })
    ]
    ))
    .pipe(gulp.dest( dstGlob ));
});
// svg画像の圧縮タスク
gulp.task('svgmin', function(){
    var srcGlob = paths.srcDir + '/*.+(svg)';　//圧縮前画像ファイル
    var dstGlob = paths.dstDir;　//圧縮後画像ファイル
    gulp.src( srcGlob )
    .pipe(changed( dstGlob ))
    .pipe(svgmin())
    .pipe(gulp.dest( dstGlob ));
});


gulp.task('default', ['server', 'sass', 'ejs'], function() {
  gulp.watch('../scss/**/*.scss', ['sass']);
  gulp.watch('../ejs/**/*.ejs', ['ejs']);
  gulp.watch(paths.srcDir + '/**/*', ['imagemin','svgmin']);
});
```

ついでに、npmインストール時に生成されたpackage.jsonにもちょこっと書き加えをします。

```json:package.json
  "scripts": {
    "build": "gulp"
  }
```

"scripts"の部分を上記のように書き加えることによって、
コマンドラインに"gulp"と入力するだけでgulpが実行されます。

さらに、meta.jsonをejs配下に入れておきます。説明は割愛。
この環境の場合、これがないとejsが動きません。

[詳しくはこちら](https://qiita.com/irie_toku/items/9551c9001bf66d87c7d0)

上記の記事でejsの扱い方を確認して頂ければ。

ここまできたら、後はコマンドラインでプロジェクトルートまで移動し、gulpを実行するだけです。
ejsにejsファイルと画像ファイルを置いていたら、同じディレクトリ構造のファイルがhtml配下にも生成されます。
scssも同様。html配下にあるcssフォルダにcssファイルが生成されます。お疲れ様でした。