Gulp with PHP, Sass, Javascript (Watching, Minifying, Live Reload)

2020년 4월 26일

회사내 프로젝트를 진행하면서 퍼블리싱 진행시 build system을 도입하지 않아 생산성이 떨어진다고 생각되었습니다. scss과 es6 문법을 쓸 수 없는 환경과 구형 브라우저(ie9 이상)지원해야 하는 환경이었습니다. 개발단계로 넘어가기 전에 퍼블리싱단계에서 최적화를 진행하기 위해 gulp 로 퍼블리싱 개발환경을 구성했습니다. (회사내에서 사용하는 폴더구조를 참조하여 셋팅을 구성했습니다.)

목표

  1. css/js 단일 파일로 압축해서 제공
  2. img 용량 최소화 (imgmin)
  3. babel을 통한 js 컴파일
  4. scss 컴파일
  5. css vendor prefix 자동 생성
  6. php local server 실행
  7. php, scss, js파일 수정시 브라우저 자동반영

package.json

{
  "name": "gulp-php-project",
  "version": "1.0.0",
  "description": "gulp-php-project",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "uxis",
  "license": "",
  "devDependencies": {
    "@babel/core": "^7.9.0",
    "@babel/preset-env": "^7.9.5",
    "browser-sync": "^2.26.7",
    "del": "^5.1.0",
    "gulp": "^4.0.2",
    "gulp-autoprefixer": "^7.0.1",
    "gulp-babel": "^8.0.0",
    "gulp-changed": "^4.0.2",
    "gulp-concat": "^2.6.1",
    "gulp-connect": "^5.7.0",
    "gulp-connect-php": "^1.0.3",
    "gulp-imagemin": "^7.1.0",
    "gulp-minify-css": "^1.2.4",
    "gulp-order": "^1.2.0",
    "gulp-sass": "^4.1.0",
    "gulp-sourcemaps": "^2.6.5",
    "gulp-uglify": "^3.0.2"
  },
  "browserslist": [
    "> 1%",
    "ie >= 8",
    "edge >= 15",
    "ie_mob >= 10",
    "ff >= 45",
    "chrome >= 45",
    "safari >= 7",
    "opera >= 23",
    "ios >= 7",
    "android >= 4",
    "bb >= 10"
  ]
}

gulpfile.js

var gulp = require("gulp");
var concat = require("gulp-concat");
var order = require("gulp-order");
//js
var babel = require("gulp-babel");
var uglify = require("gulp-uglify");
//css
var sass = require("gulp-sass");
var minificss = require("gulp-minify-css");
var autoprefixer = require("gulp-autoprefixer");
//img
var imagemin = require("gulp-imagemin");
var changed = require("gulp-changed");
var del = require("del");
//php live server
var phpConnect = require("gulp-connect-php");
var browsersync = require("browser-sync");
//path
var devsrc = "dev_share";
var pubsrc = "share";
var paths = {
  dev: {
    js: devsrc + "/js/*.js",
    vendor_js: devsrc + "/js/vendor/*.js",
    scss: devsrc + "/css/**/*.scss",
    img: devsrc + "/img/*+(png|jpg|gif)",
  },
  pub: {
    js: pubsrc + "/js",
    css: pubsrc + "/css",
    img: pubsrc + "/img",
  },
};

function gulp_js() {
  return gulp
    .src(paths.dev.js, { sourcemaps: true })
    .pipe(babel())
    .pipe(uglify())
    .pipe(concat("scripts.js"))
    .pipe(gulp.dest(paths.pub.js))
    .pipe(browsersync.reload({ stream: true }));
}

function gulp_vendor_js() {
  return gulp
    .src(paths.dev.vendor_js)
    .pipe(gulp.dest(paths.pub.js + "/vendor"))
    .pipe(browsersync.reload({ stream: true }));
}

function gulp_scss() {
  return gulp
    .src(paths.dev.scss, { sourcemaps: true })
    .pipe(
      autoprefixer({
        cascade: false,
      })
    )
    .pipe(
      order(["lib/*.scss", "fonts.scss", "reset.scss", "layout.scss", "*.scss"]) //우선순위 적용
    )
    .pipe(sass().on("error", sass.logError))
    .pipe(minificss())
    .pipe(concat("style.css"))
    .pipe(gulp.dest(paths.pub.css))
    .pipe(browsersync.reload({ stream: true }));
}
function imgmin() {
  return gulp
    .src(paths.dev.img)
    .pipe(changed(paths.pub.img))
    .pipe(imagemin([imagemin.optipng({ optimizationLevel: 5 })]))
    .pipe(gulp.dest(paths.pub.img))
    .pipe(browsersync.reload({ stream: true }));
}

function gulp_watch() {
  gulp.watch(paths.dev.js, gulp_js);
  gulp.watch(paths.dev.vendor_js, gulp_vendor_js);
  gulp.watch(paths.dev.scss, gulp_scss);
  gulp.watch(paths.dev.img, imgmin);
  gulp.watch("./**/**/*.php", browserSyncReload);
}

function connectsync() {
  phpConnect.server(
    {
      port: 8000,
      keepalive: true,
      base: ".",
    },
    function () {
      browsersync({
        proxy: "127.0.0.1:8000",
      });
    }
  );
}

function browserSyncReload(done) {
  browsersync.reload();
  done();
}

function clean() {
  return del(["./share/css", "./share/img", "./share/js"]);
}

gulp.task(
  "default",
  gulp.series(
    clean,
    gulp.parallel(
      gulp.series(gulp_js, gulp_vendor_js, gulp_scss, imgmin),
      gulp_watch,
      connectsync
    )
  )
);

설치중 생긴 문제점


  1. gulp 3.x버전으로 튜토리얼들이 많아서 gulp 4.x버전으로 전환하는 과정이 필요했다. (task실행시 배열을 사용하여 실행하는 방법에서 4버전에 새로 도입된 series, parallel을 사용해야 했다.)
  2. babel 버전 문제점 (Babel 7을 사용할 경우 : gulp-babel, @babel/core, @babel/preset-env, Babel 6를 사용할 경우 : gulp-babel@7, babel-core, babel-preset-env를 설치해야 했다.)