2020年  gulp4 必要最低限のコーディング環境

この前、プライベートで急にコーディングする機会がありましたのでその時に実際にコーディングした必要最低限の環境を共有したいと思います。(初学者むけ)

[実際の環境github](https://github.com/satouyuuki/yuuki-gulp4)

環境は以下になります。

```
macOS 10.14.6 ※windowsの方ごめんなさい
node 12.1.0(gulp4はnodeのバージョン10以上をお勧めします)
nodebrew 8.9.4(nodejsのバージョン管理ツール)
※なくてもいいですが、あると便利です
```

### gulpとは
gulpとはタスクランナーツールです。
タスクランナーは決まったタスクを順番通りまたは非同期にこなしてくれます。

* 例としては以下のようなものです。
 1. scssで書かれたものをcssにコンパイル
 2. cssにプレフィクスを付与
 3. scssファイルをwatchしつつ変更があれば自動でブラウザをリロード

これら処理を自分ででするとなると大変ですが、gulpならそれら自動で行ってくれます



* 今回行うものはコーディングに必要最低限のパッケージです
 * gulp
 * gulp-sass(cssにコンパイルしてくれるもの)
 * gulp-autoprefixer(webkitやmsなどをのプレフィックスをつけてくれる)
 * browser-sync(ブラウザを自動リロード)
 * gulp-plumber(コンパイルエラーの際にgulp.watch()中断されるのを防いでくれる

このファイル構成を行うことで以下のことができます。

* cssをscssの文法で書ける
* cssにプレフィクスを自動で付与してくれる
* ブラウザを自動リロードできる


ファイル構成

```
yuuki-gulp4/
 └──app/
     └──assets/
         |──fonts/ダウンロードしたfontなどを入れる(今回は使用しない)
         |──images/
     └──css/style.scss
     └──js/main.js
     └──index.html
 └──package.json
 └──gulpfile.js
```

### 準備編
↓nodebrewをインストールしてない場合
[参考記事](https://qiita.com/mame_daifuku/items/373daf5f49ee585ea498)

```
nodebrewがインストール済みか確認
$ nodebrew -v

バージョンv12.1.0をローカルにインストールする
$ nodebrew install v12.1.0

バージョンを切り替える
$ nodebrew use v12.1.0

バージョンが切り替わってるか確認
$ node -v
```

### 必要なパッケージをインストール

```
package.jsonを作成
$ npm init -y

必要なパッケージをインストール
$ npm install --save-dev gulp browser-sync gulp-autoprefixer gulp-plumber gulp-sass
```
するとこのようにdevDependencies(依存パッケージ)に必要なものがインストールされてるのがわかります。



```json:package.json

"devDependencies": {
    "browser-sync": "^2.26.7",
    "gulp": "^4.0.2",
    "gulp-autoprefixer": "^7.0.1",
    "gulp-plumber": "^1.2.1",
    "gulp-sass": "^4.0.2"
}
```

"scripts"の部分を以下のように変更してください。

```json:package.json
"scripts": {
    "start": "gulp",
    "watch": "gulp watch"
},
```

そしたらpackage.jsonと同じ階層にgulpfile.jsを作成して下記のコードを作成してください。


```javascript:gulpfile.js

//分割代入をして gulp.hoge()と書かずにhoge()と書ける
const {src, dest, task, watch, series, parallel} = require("gulp");

const sass = require("gulp-sass");
const autoprefixer = require("gulp-autoprefixer");
const browserSync = require("browser-sync").create();
const plumber = require("gulp-plumber");

// 必要な読み込むファイルpathと出力するファイルpathを変数にする
const styleSRC = "./app/css/style.scss";
const styleURL = "./dist/css/";
const htmlSRC = "./app/*.html";
const htmlURL = "./dist/";
const jsSRC = "./app/js/*.js";
const jsURL = "./dist/js/";
const imgSRC = "./app/assets/images/**/*";
const imgURL = "./dist/assets/images/";
const fontsSRC = "./app/assets/fonts/**/*";
const fontsURL = "./dist/assets/fonts/";

// yuuki-gulp4/dist以下をローカルサーバーのルートとする
function browser_sync() {
  browserSync.init({
    server: {
      baseDir: "./dist/"
    }
  });
};
// 自動でブラウザをリロードする
function reload (done) {
  browserSync.reload();
  done();
}

function css(done) {
  src(styleSRC)
    .pipe(sass({
　　　 // エラーを出力&css圧縮せずcssに展開
      errLogToConsole: true,
      outputStyle: "expanded"
    }))
    //これがないとコンパイルエラーの時にgulpが中断してしまう
    .on('error', console.error.bind(console))
　　 //プレフィックス付与
    .pipe(autoprefixer())
    .pipe(dest(styleURL))
    .pipe(browserSync.stream());
  done();
};

// watch()を中断させない
function triggerPlumber(src_file, url_file) {
  return src(src_file)
    .pipe(plumber())
    .pipe(dest(url_file));
};

function images() {
  return triggerPlumber(imgSRC, imgURL);
}

function fonts() {
  return triggerPlumber(fontsSRC, fontsURL);
}

function html() {
  return triggerPlumber(htmlSRC, htmlURL);
}

function js() {
  return triggerPlumber(jsSRC, jsURL);
}

function watch_files() {
  watch(styleSRC, series(css, reload));
  watch(jsSRC, series(js, reload));
  watch(imgSRC, series(images, reload));
  watch(fontsSRC, series(fonts, reload));
  watch(htmlSRC, series(html, reload));
}

//上の関数を名前付きで定義する
task("css", css);
task("js", js);
task("images", images);
task("fonts", fonts);
task("html", html);

task("default", parallel(css, js, images, fonts, html));

task("watch", parallel(browser_sync, watch_files));
```

* 実行方法

```
ビルドをする
$ npm start

コーディングする
$ npm run watch
```


今回行わなかったけど必要なタスク

* babel(javascriptをIEや古いブラウザに対応するために必要)
* 画像圧縮系タスク(成果物として納品するために必要)
* キャッシュ対策パラメータ(style.css?1111など)

これらは次回のgulp4で盛り込んで行きます