最近のgulp gulp4 + webpack4

私が最近使っているgulpの設定を公開します。
webpackでjsをまとめています。

webpackが必要ない場合は[こちら](https://qiita.com/koba08/items/6484504bd90ca6fd5b91)
gulp v3系の設定は[こちら](https://qiita.com/koba08/items/edcfba64959965194ac4)

## ディレクトリ構造

`/source/`内のファイルが`/dist/assets/`に出力されます。

``` 
.
├── dist
│   └── assets
│       ├── css
│       ├── img
│       ├── js
│       │   └── bundle.js
│       ├── sourcemaps
│       └── ssi
├── gulpfile.js
├── node_modules
├── package-lock.json
├── package.json
├── src
│   ├── img
│   ├── js
│   └── scss
└── webpack.config.js
```

## gulpfile.js


```js:gulpfile.js

const gulp = require("gulp");
const browserSync = require("browser-sync");
const ssi = require("connect-ssi");
const sass = require("gulp-sass");
const autoprefixer = require("gulp-autoprefixer");
const glob = require("gulp-sass-glob");
const notify = require("gulp-notify");
const plumber = require("gulp-plumber");
const babel = require("gulp-babel");
const uglify = require("gulp-uglify-es").default;
const imagemin = require("gulp-imagemin");
const mozjpeg = require("imagemin-mozjpeg");
const pngquant = require("imagemin-pngquant");
const changed = require("gulp-changed");
const webpackStream = require("webpack-stream");
const webpack = require("webpack");
const webpackConfig = require("./webpack.config");

const paths = {
  rootDir: "dist/",
  scssSrc: "src/scss/**/*.scss",
  jsSrc: "src/js/**/*.js",
  imgSrc: "src/img/**/*",
  outCss: "dist/assets/css",
  outJs: "dist/assets/js",
  outImg: "dist/assets/",
};

// browser sync
function browserSyncFunc(done){
  browserSync.init({
      server: {
          baseDir: paths.rootDir,
          middleware: [
            ssi({
              baseDir: paths.rootDir,
              notify: false, //通知
              ext: ".html"
            })
          ]
      },
      port: 4000,
      reloadOnRestart: true
  });
  done();
}

// sass
function sassFunc() {
    return gulp.src(paths.scssSrc , {
        sourcemaps: true
    })
    .pipe(plumber({
        errorHandler: notify.onError('<%= error.message %>'),
    }))
    .pipe(glob())
    .pipe(sass({
        outputStyle: 'compressed'
    }))
    .pipe(autoprefixer({
      browsers: ["last 2 versions", "ie >= 11", "Android >= 4"],
      cascade: false
    }))
    .pipe(gulp.dest(paths.outCss, {
        sourcemaps: './sourcemaps'
    }))
    .pipe(browserSync.stream());
}

// js
function jsFunc() {
  return plumber({
    errorHandler: notify.onError('<%= error.message %>'),
  })
  .pipe(webpackStream(webpackConfig, webpack))
  .pipe(babel())
  .pipe(uglify({}))
  .pipe(gulp.dest(paths.outJs));
}

// img
function imgFunc() {
  return gulp.src(paths.imgSrc)
  .pipe(changed(paths.outImg))
  .pipe(gulp.dest(paths.outImg))
  .pipe(imagemin(
    [
      mozjpeg({
        quality: 80 //画像圧縮率
      }),
      pngquant()
    ],
    {
      verbose: true
    }
  ))
}

// watch
function watchFunc(done) {
  gulp.watch(paths.scssSrc, gulp.parallel(sassFunc));
  gulp.watch(paths.jsSrc, gulp.parallel(jsFunc));
  gulp.watch(paths.imgSrc, gulp.parallel(imgFunc));
  done();
}

  // scripts tasks
gulp.task('default',
gulp.parallel(
  browserSyncFunc, watchFunc, sassFunc, jsFunc,imgFunc
  )
);


```

## .babelrc

``` :.babelrc
{
    "presets": [
        [
            "@babel/preset-env",
            {
                "targets": ">0.25% in JP, not ie <= 10, not op_mini all"
            }
        ]
    ]
}
```
・その他設定方法
 [babel公式サイト](https://babeljs.io/docs/en/next/babel-preset-env)

・targetsの対象ブラウザは下記のサイトで確認できます。
 [browserl.ist](https://browserl.ist/)

## webpack.config.js

``` :webpack.config.js

module.exports = {
    // モード値を production に設定すると最適化された状態で、
    // development に設定するとソースマップ有効でJSファイルが出力される
    mode: "development",
  
    // メインのJS
    entry: "./src/js/main.js",
    // 出力ファイル
    output: {
      filename: "./bundle.js"
    }
  }

```


## package.json

``` :package.json
{
  "name": "name",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@babel/core": "^7.4.3",
    "@babel/preset-env": "^7.4.3",
    "babel-loader": "^8.0.5",
    "browser-sync": "^2.26.5",
    "connect-ssi": "^1.1.1",
    "gulp": "^4.0.1",
    "gulp-autoprefixer": "^6.1.0",
    "gulp-babel": "^8.0.0",
    "gulp-changed": "^3.2.0",
    "gulp-imagemin": "^5.0.3",
    "gulp-notify": "^3.2.0",
    "gulp-plumber": "^1.2.1",
    "gulp-sass": "^4.0.2",
    "gulp-sass-glob": "^1.0.9",
    "gulp-uglify-es": "^1.0.4",
    "imagemin-mozjpeg": "^8.0.0",
    "imagemin-pngquant": "^7.0.0",
    "webpack": "^4.30.0",
    "webpack-stream": "^5.2.1"
  }
}

```

## プラグインの説明

- [browser-sync](https://www.npmjs.com/package/browser-sync) ブラウザ確認環境
- [connect-ssi](https://www.npmjs.com/package/connect-ssi) SSIを使用可能にする
- [gulp-sass](https://www.npmjs.com/package/gulp-sass) SASSを使用可能にする
- [gulp-autoprefixer](https://www.npmjs.com/package/gulp-autoprefixer) ベンダープレフィックス付与
- [gulp-sass-glob](https://www.npmjs.com/package/gulp-sass-glob) import文でワイルドカードが使用可能になる
- [gulp-plumber](https://www.npmjs.com/package/gulp-plumber) エラー時の強制停止を防止
- [gulp-babel](https://www.npmjs.com/package/gulp-babel) JavaScriptのコード変換
- [gulp-uglify-es](https://www.npmjs.com/package/gulp-uglify-es) JavaScriptのminify化
 `gulp-uglify`だとES6に対応していないため、`gulp-uglify-es`を使用する必要があります。
- [gulp-imagemin](https://www.npmjs.com/package/gulp-imagemin) 画像圧縮
- [imagemin-mozjpeg](https://www.npmjs.com/package/imagemin-mozjpeg) Mozilla製のjpegエンコーダ　画像圧縮時の品質は80%に設定しています。
- [imagemin-pngquant](https://www.npmjs.com/package/imagemin-pngquant) pngエンコーダ
- [gulp-changed](https://www.npmjs.com/package/gulp-changed) 更新されたファイルのみ処理させるプラグイン

## PHPを使いたい場合

「gulp-connect-php」を使ったらうまくいきました。
browser syncの箇所を下記に変更しました。

```
const connect = require('gulp-connect-php');

// browser sync
function browserSyncFunc(done){
  connect.server({
    base:paths.rootDir,
    livereload: true,
    port:8000
  }, function (){
    browserSync.init({
      proxy: "localhost:8000",
      middleware: [
        ssi({
          baseDir: paths.rootDir,
          notify: false, //通知
          ext: ".html"
        })
      ]
    });
  });
  done();
}
```

## 参考サイト

[Gulpで始めるwebpack 4入門](https://qiita.com/tonkotsuboy_com/items/2d4f3862e6d05dc0bea1)