[ 前端工具 ] - gulp, Babel, SCSS, uglyfy


Posted by krebikshaw on 2020-08-28

gulp 簡介

gulp 類似一種任務管理工具,把一些任務自動化,像是:壓縮圖片、移動檔案、compile css、轉換 JavaScript、minify js or css

  • webpack 也可以當成 gulp 的任務之一

先貼上最後 gulpfile.js 的內容

const { src, dest, series, parallel } = require('gulp');
const babel = require('gulp-babel');
const sass = require('gulp-sass');
const uglify = require('gulp-uglify');
const rename = require('gulp-rename');
const cleanCSS = require('gulp-clean-css');

sass.compiler = require('node-sass');

function compileJS() {
  return src('src/*.js')
    .pipe(babel())
    .pipe(dest('dist'))
    .pipe(uglify())
    .pipe(rename({ extname: '.min.js' }))
    .pipe(dest('dist'))
}

function compileCSS() {
  return src('src/*.scss')
    .pipe(sass().on('error', sass.logError))
    .pipe(dest('css'))
    .pipe(cleanCSS({compatibility: 'ie8'}))
    .pipe(rename({ extname: '.min.css' }))
    .pipe(dest('css'))
}

exports.compileJS = compileJS
exports.compileCSS = compileCSS
exports.default = parallel(compileCSS, compileJS)

說明

const { src, dest, series, parallel } = require('gulp'); // 引入待會需要使用的 gulp 內建語法
const babel = require('gulp-babel'); // 引入 Babel
const sass = require('gulp-sass'); // 引入 sass
const uglify = require('gulp-uglify'); // 引入 JS 壓縮程式 
const rename = require('gulp-rename'); // 引入重新命名程式
const cleanCSS = require('gulp-clean-css'); // 引入 CSS 壓縮程式

sass.compiler = require('node-sass'); // 引入 sass 編譯程式

function compileJS() { // 編譯 JS 檔
  return src('src/*.js') // 取得 src 這個資料夾底下的所有 .js 檔
    .pipe(babel()) // 將這些檔案都進行 babel 轉換
    .pipe(dest('dist')) // 處理完放到 dist 這個資料夾底下
    .pipe(uglify()) // 再將剛剛 babel 處理後的檔案做壓縮
    .pipe(rename({ extname: '.min.js' })) // 為了區分壓縮及未壓縮的檔案,將有壓縮過的檔案都換上 .min.js 這個副檔名
    .pipe(dest('dist')) // 把這些 .min.js 檔案放到 dist 這個資料夾底下
}

function compileCSS() { // 編譯 CSS 檔
  return src('src/*.scss') // 取得 src 這個資料夾底下的所有 .scss 檔
    .pipe(sass().on('error', sass.logError)) // 將這些檔案都進行 sass 轉換
    .pipe(dest('css')) // 處理完放到 css 這個資料夾底下
    .pipe(cleanCSS({compatibility: 'ie8'})) // 再將剛剛 sass 處理後的檔案做壓縮
    .pipe(rename({ extname: '.min.css' })) // 為了區分壓縮及未壓縮的檔案,將有壓縮過的檔案都換上 .min.css 這個副檔名
    .pipe(dest('css')) // 把這些 .min.css 檔案放到 css 這個資料夾底下
}

exports.compileJS = compileJS // 在 CLI 下 npx gulp compileJS 可單獨執行 compileJS() 程序
exports.compileCSS = compileCSS // 在 CLI 下 npx gulp compileCSS 可單獨執行 compileCSS() 程序
exports.default = series(compileCSS, compileJS) //  在 CLI 下 npx gulp 會先執行 compileJS() 程序,再執行 compileCSS() 程序
exports.default = parallel(compileCSS, compileJS) //  在 CLI 下 npx gulp 會「同時」執行 compileJS() 及 compileCSS() 程序

事前安裝

必須先按照下列流程安裝套件才可以執行上面的 gulp

  • 將 node, npm, npx 先安裝完成

SCSS 的部分:

  • npm install -g sass: 安裝 sass

Babel 的部分:

  • npm init:產生 package.json
  • npm install --save-dev @babel/core @babel/cli:安裝 Babel
  • 打開 package.json,在 "scripts": { } 底下加上 "build": "babel src -d lib"
  • 在根目錄新增一個 .babelrc 檔案,裡面寫上 { "presets": ["@babel/preset-env"] }

gulp 的部分:

  • npm install --global gulp-cli:安裝 gulp
  • 在根目錄新增一個 gulpfile.js 檔案
  • npm install --save-dev gulp-babel:安裝 gulp-babel
  • npm install node-sass gulp-sass --save-dev:安裝 gulp-sass
  • npm install --save-dev gulp-uglify:安裝 gulp-uglify
  • npm install --save-dev gulp-rename:安裝 gulp-rename
  • npm install gulp-clean-css --save-dev:安裝 gulp-clean-css

好用範例

const gulp = require('gulp');
const { src, dest } = require('gulp');
const pug = require('gulp-pug');
const sass = require('gulp-sass');
const postcss = require('gulp-postcss');
const uncss = require('postcss-uncss');
const autoprefixer = require('autoprefixer');
const minifyCSS = require('gulp-csso');
const rename = require('gulp-rename');
const sourcemaps = require('gulp-sourcemaps');
const connect = require('gulp-connect');
const imageMin = require('gulp-imagemin');
const del = require('del')
const browserify = require("browserify");
const babelify = require("babelify");
const source = require("vinyl-source-stream");
const glob = require('glob');
const es = require('event-stream');
const uglify = require('gulp-uglify');
const buffer = require('vinyl-buffer');
const svgSprite = require('gulp-svg-sprite');
const merge = require('merge-stream');
const gulpif = require('gulp-if');
const fontmin = require('gulp-fontmin-woff2');

// run minfont.js to get this string
const fontText = '\uf028\uf164\uf57d\uf1c0\uf7d9\uf233\uf201\uf3ed\uf126\uf51c\uf06e\uf0c9\uf35d\uf077\uf00c\uf2bd\uf061\uf063\uf062\uf073\uf550\uf14a\uf35a\uf0c5\uf30b\uf09b\uf082\uf23a\uf41b\uf3b8\uf13b\uf38b\uf268\uf457'
const env = process.env.NODE_ENV;

console.log('--- current mode: ', env);

const base = {
  src: 'src',
  dest: 'docs',
}
const paths = {
  css: {
    src: `${base.src}/scss/*.scss`,
    dest: `${base.dest}/css`,
  },
  js: {
    src: `${base.src}/js/**/*.js`,
    dest: `${base.dest}/js`,
  },
  html: {
    src: `${base.src}/html/*.pug`,
    dest: base.dest,
  },
  image: {
    src: `${base.src}/image/*.+(jpg|jpeg|gif|png|svg)`,
    dest: `${base.dest}/image`,
  }
};

function clean() {
  return del([
    `${base.dest}/*`,
    `!${base.dest}/.git`,
    `!${base.dest}/.gitignore`,
    `!${base.dest}/robots.txt`,
  ]);
}

const js = (done) => {
  glob('./src/js/bundle/*.js', function (err, files) {
    if (err) done(err);

    files.push('src/js/index.js');
    var tasks = files.map(function (entry) {
      return browserify({
        entries: [entry],
        debug: env === 'development',
        transform: [babelify.configure(),]
      })
        .bundle()
        .pipe(source(entry.match(/[^\\/]+$/)[0]))
        .pipe(buffer())
        .pipe(sourcemaps.init({ loadMaps: true }))
        .pipe(uglify())
        .pipe(gulpif(env === 'development', sourcemaps.write()))
        .pipe(rename({
          extname: '.bundle.js'
        }))
        .pipe(gulp.dest(paths.js.dest));
    });
    es.merge(tasks).on('end', done)
      .pipe(connect.reload());
  })
}

function html() {
  return src(paths.html.src)
    .pipe(pug())
    .pipe(dest(base.dest))
    .pipe(connect.reload())
}

function sprite() {
  const config = {
    shape: {
      dimension: {
        maxWidth: 300,
        maxHeight: 300,
      },
      spacing: {
        padding: 2,
      },
    },
    mode: {
      view: {
        bust: false,
        example: true,
        layout: 'vertical',
        sprite: 'sprite.svg',
        render: {
          scss: { dest: '_sprite.scss' }
        }
      },
    }
  };
  return src('src/image/sprite/*.svg')
    .pipe(svgSprite(config))
    .pipe(gulp.dest('src/scss/sprite'));
}

function css() {
  const processors = [
    autoprefixer({ overrideBrowserslist: ['last 2 version'] }),
  ];

  if (env === 'production') {
    processors.push(
      uncss({
        html: ['docs/*.html'],
      })
    )
  }
  const css = gulp.src(paths.css.src)
    .pipe(sourcemaps.init())
    .pipe(sass().on('error', sass.logError))
    .pipe(postcss(processors))
    .pipe(minifyCSS())
    .pipe(gulpif(env === 'development', sourcemaps.write()))
    .pipe(rename({
      basename: 'main',
      suffix: '.min'
    }))
    .pipe(dest(paths.css.dest))
    .pipe(connect.reload())

  const copySprite = gulp.src('src/scss/sprite/view/*.svg')
    .pipe(gulp.dest('docs/css/'))

  return merge(css, copySprite);
}

function font() {
  return src(`${base.src}/webfonts/*.ttf`)
    .pipe(fontmin({
          text: fontText,
      }))
    .pipe(dest(`${base.dest}/webfonts`))
}

function img() {
  return src(paths.image.src)
    .pipe(imageMin())
    .pipe(dest(paths.image.dest))
    .pipe(connect.reload())
}

function beforeEnd() {
  return src(`${base.src}/statics/*`)
    .pipe(dest(`${base.dest}`))
}

function watch(done) {
  if (env !== 'production') {
    gulp.watch(`${base.src}/scss/**/*`, css);
    gulp.watch(`${base.src}/html/**/*`, html);
    gulp.watch(`${base.src}/js/**/*`, js);
    gulp.watch(`${base.src}/image/*`, img);
    gulp.watch(`${base.src}/image/*`, gulp.series(sprite, css));
  }
  done();
}

function server(done) {
  if (env !== 'production') {
    var options = {
      root: 'docs',
      port: 8080,
      livereload: true,
    };
    connect.server(options);
  }
  done();
};

const resource = gulp.series(js, gulp.parallel(html, css, img, font))
const build = gulp.series(clean, sprite, resource, beforeEnd, gulp.parallel(watch, server))

exports.clean = clean;
exports.default = build;
exports.js = js;
exports.css = css
exports.img = img
exports.beforeEnd = beforeEnd
exports.sprite = gulp.series(sprite, css);

#gulp







Related Posts

軟體工程師面試資源最簡整理與技巧分享

軟體工程師面試資源最簡整理與技巧分享

[ JavaScript  12 ]  ES6 新增特性

[ JavaScript 12 ] ES6 新增特性

綜合能力測驗 - 破關紀錄

綜合能力測驗 - 破關紀錄


Comments