Gulp

安裝環境

  1. Node.js

  2. gulp-cli

$ sudo npm install gulp-cli -g

環境建置

產生出一個 package.json

$ npm init

安裝 gulp 4.x.x

npm install --sava-dev gulp

新增 gulpfile.js

新增資料夾 source 裡面在新增 index.html


範例: 使用 task 複製文件至指定資料夾下

gulpfile.js

var gulp = require('gulp');

gulp.task('copyHTML', function () {
return gulp.src('./source/**/*.html')
.pipe(gulp.dest('./public/'))
})

出現 ReferenceError: primordials is not defined 連結

原因是 node v12.x.xgulp v3.9.x

解決方法 (二擇一)

  1. node 降至 v11
  2. gulp 升至 v4

本來使用 方法1 是由於課程使用 gulp 3.9.1

但是發現 解除安裝 Node 太過麻煩

所以改用 方法2

$ gulp copyHTML

會看到 source 資料夾下的 index.html

複製出一份到 public 資料夾下


gulp-jade

npm-jade

安裝

$ npm install --save gulp-jade

Quick Start

  1. sourceindex.html 刪除,新建 index.jade
  2. public 資料夾刪除

gulpfile.js

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

gulp.task('jade', function() {
// var YOUR_LOCALS = {};

return gulp.src('./source/**/*.jade')
.pipe(jade({
// locals: YOUR_LOCALS
pretty: true
}))
.pipe(gulp.dest('./public/'))
});

因為 gulp v4 的關係請在 gulp.src 前面加上 return

不然會跳出以下訊息

  • The following tasks did not complete: jade
  • Did you forget to signal async completion?
$ gulp jade

就會成功將 .jade 編譯成 .html

pretty: true : 會將 .html 內容展開

沒有加上 pretty: true 就會是 壓縮過後.html


gulp-sass

npm-sass

安裝

$ npm install --save gulp-sass

Quick Start

source 資料夾下 新增 scss 資料夾 裡面再 新增 all.scss

all.scss

$primary-color: red;

body {
color: $primary-color;
}

gulpfile.js

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

gulp.task('sass', function () {
return gulp.src('./source/scss/**/*.scss')
.pipe(sass().on('error', sass.logError))
.pipe(gulp.dest('./public/css/'));
});

$ gulp sass

看有沒有將 .scss 編譯出 .css


gulp.watch & gulp.series & gulp.parallel

gulpfile.js

gulp.task('watch', function () {
gulp.watch('./source/scss/**/*.scss', ['sass'] );
});

使用上面這段程式碼會出現錯誤 連結

Error: watching ./source/scss/**/*.scss: watch task has to be a function (optionally generated by using gulp.parallel or gulp.series)

這是因為 gulp v4 增加了 gulp.parallelgulp.series 兩個方法

修改成下方

gulp.task('watch', function () {
gulp.watch('./source/scss/**/*.scss', gulp.series('sass'));
});

在執行

$ gulp watch

嘗試將 all.scss 裡面的 red 改成 blue 看有沒有編譯成功出在 all.css

會是這樣呈現如下

$ gulp watch
[11:44:50] Using gulpfile ~/Desktop/DemoGulp/gulpfile.js
[11:44:50] Starting 'watch'...
[11:44:59] Starting 'sass'...
[11:44:59] Finished 'sass' after 24 ms

gulp.parallel : 同時執行

gulp.series : 依序執行

這兩個方法可以一起搭配使用 !!!


整合 jade sass watch

gulpfile.js

gulp.task('watch', function () {
gulp.watch('./source/scss/**/*.scss', gulp.series('sass'));
gulp.watch('./source/**/*.jade', gulp.series('jade'));
});

gulp.task('default',
gulp.parallel('jade', 'sass', 'watch')
);

terminal 直接輸入 gulp Enter

$ gulp

就會開始同時執行 gulp.task 'default' 裡面的其它任務


gulp-plumber

npm-plumber

避免在監控 (watch) 時,因為出現錯誤而停止了整個監控 !

但是在 gulp v4,我現在還沒加上就已經有這個功能了。

現階段還是照著教學加上去

安裝

$ npm install --save gulp-plumber

gulp.src 後面都加上 .pipe(plumber())

gulp.task('jade', function() {

return gulp.src('./source/**/*.jade')
.pipe(plumber())
.pipe(jade({
pretty: true
}))
.pipe(gulp.dest('./public/'))
});

gulp.task('sass', function () {
return gulp.src('./source/scss/**/*.scss')
.pipe(plumber())
.pipe(sass().on('error', sass.logError))
.pipe(gulp.dest('./public/css/'));
});

更高明的 CSS 優化流程

gulp-postcss & autoprefixer

npm-postcss

npm-autoprefixer

Browserslist

$ npm install --save gulp-postcss autoprefixer

配置

all.scss

.card {
transform: rotate(120deg);
filter: blur(3px);
}

gulpfile.js

var postcss = require('gulp-postcss');
var autoprefixer = require('autoprefixer');

gulp.task('sass', function () {

var plugins = [
autoprefixer({ browsers: ['last 3 version', '> 5%', 'ie 6-8'] })
];

return gulp.src('./source/scss/**/*.scss')
.pipe(plumber())
.pipe(sass().on('error', sass.logError))
// 編譯完成 CSS

.pipe(postcss(plugins))
.pipe(gulp.dest('./public/css/'));
});

執行時會出現以下錯誤

Replace Autoprefixer browsers option to Browserslist config.

Use browserslist key in package.json or .browserslistrc file.

Using browsers option cause some error. Browserslist config 

can be used for Babel, Autoprefixer, postcss-normalize and other tools.

----------------------------------------------------------------------------
*                                                                          *
*   If you really need to use option, rename it to overrideBrowserslist.   *
*                                                                          *
----------------------------------------------------------------------------

  Learn more at:

    https://github.com/browserslist/browserslist#readme

    https://twitter.com/browserslist

browsers 修改為 overrideBrowserslist 就可以囉


執行 $ gulp 會發現 all.css 有加上前綴詞

.card {
-webkit-transform: rotate(120deg);
-ms-transform: rotate(120deg);
transform: rotate(120deg);
-webkit-filter: blur(3px);
filter: blur(3px); }

官方建議配置

package.json

"browserslist": [
"last 3 version",
"> 5%",
"IE 10"
]

gulpfile.js

gulp.task('sass', function () {

// var plugins = [
// autoprefixer({ overrideBrowserslist: [ 'last 3 version', '> 5%', 'ie 6-8' ] })
// ];

return gulp.src('./source/scss/**/*.scss')
.pipe(plumber())
.pipe(sass().on('error', sass.logError))
// 編譯完成 CSS

// .pipe(postcss(plugins))
.pipe(postcss( [autoprefixer()] )) // 直接引入 autoprefixer

.pipe(gulp.dest('./public/css/'));
});

gulp-load-plugins

npm-gulp-load-plugins

安裝

$ npm install --save gulp-load-plugins

配置

gulpfile.js

var $ = require('gulp-load-plugins')();

刪除

var jade = require('gulp-jade');
var sass = require('gulp-sass');
var plumber = require('gulp-plumber');
var postcss = require('gulp-postcss');

將有使用到的套件前面加上 $.

gulp.task('jade', function() {

return gulp.src('./source/**/*.jade')
.pipe($.plumber())
.pipe($.jade({
pretty: true
}))
.pipe(gulp.dest('./public/'))
});

gulp.task('sass', function () {
return gulp.src('./source/scss/**/*.scss')
.pipe($.plumber())
.pipe($.sass().on('error', $.sass.logError))
.pipe($.postcss( [autoprefixer()] ))
.pipe(gulp.dest('./public/css/'));
});

記得在 $ gulp 測試看看有無錯誤


gulp-babel

npm-babel

安裝

$ npm install --save gulp-babel @babel/core @babel/preset-env
$ npm install --save gulp-concat gulp-sourcemaps

配置

source 資料夾下 新增 all.js all2.js

all.js

let newFun = () => {
console.log('a');
}

newFun();

all2.js

let newFun2 = () => {
console.log('b');
}

newFun2();

gulpfile.js

gulp.task('babel', () => {
return gulp.src('./source/js/**/*.js')
.pipe($.babel({
presets: ['@babel/env']
}))
.pipe(gulp.dest('./public/js/'))
});

gulp.task('watch', function () {
gulp.watch('./source/scss/**/*.scss', gulp.series('sass'));
gulp.watch('./source/**/*.jade', gulp.series('jade'));
gulp.watch('./source/**/*.js', gulp.series('babel'));
});

gulp.task('default',
gulp.parallel('jade', 'sass', 'babel', 'watch')
);

gulp-concat

會將 source > js 裡面的兩隻 .js 合併為一個

gulpfile.js

gulp.task('babel', () => {
return gulp.src('./source/js/**/*.js')
.pipe($.babel({
presets: ['@babel/env']
}))
.pipe($.concat('all.js'))
.pipe(gulp.dest('./public/js/'))
});

gulp-sourcemaps

會將內容正確顯示出沒有合併前的檔案位置

gulpfile.js

gulp.task('babel', () => {
return gulp.src('./source/js/**/*.js')
.pipe($.sourcemaps.init())
.pipe($.babel({
presets: ['@babel/env']
}))
.pipe($.concat('all.js'))
.pipe($.sourcemaps.write('.'))
.pipe(gulp.dest('./public/js/'))
});

Bower - 前端套件管理

npm-bower

安裝

sudo npm install -g bower

gulp 與 bower 流程串接

安裝 main-bower-files

main-bower-files

$ npm install --save main-bower-files

安裝 jquery & bootstrap

$ bower install --save jquery
$ npm install --save bootstrap

配置

jquery.js 另存在這個地方 ./.tmp/vendors

gulpfile.js

gulp.task('bower', function() {
return gulp.src(mainBowerFiles())
.pipe(gulp.dest('./.tmp/vendors'))
});

合併 bootstrap & jquery 的 js

gulpfile.js

gulp.task('vendorJs', () => {
return gulp.src([
'./.tmp/vendors/**/*.js',
'./node_modules/bootstrap/dist/js/bootstrap.bundle.min.js'
])
.pipe($.concat('vendors.js'))
.pipe(gulp.dest('./public/js/'))
});

gulp-order

外部載入的套件如果需要排序 gulp-order

像是 BootstrapjQuery 會有前後相依的需求

gulpfile.js

gulp.task('vendorJs', () => {
return gulp.src([
'./.tmp/vendors/**/*.js',
'./node_modules/bootstrap/dist/js/bootstrap.bundle.min.js'
])
.pipe($.order([
'jquery.js',
'bootstrap.js'
]))
.pipe($.concat('vendors.js'))
.pipe(gulp.dest('./public/js/'))
});

browser-sync

Browsersync + Gulp.js

安裝

$ npm install --save browser-sync

配置

gulpfile.js

var browserSync = require('browser-sync').create();

gulp.task('browser-sync', function() {
browserSync.init({
server: {
baseDir: "./public"
},
reloadDebounce: 2000 // 延遲 2秒重置
});
gulp.watch("./source/scss/**/*.scss", gulp.series('sass'));
gulp.watch('./source/**/*.js', gulp.series('babel'));
gulp.watch("./source/**/*.jade", gulp.series('jade')).on('change', browserSync.reload);
});

還有在 gulp.task(['jade', 'sass', 'babel']).pipe(gulp.dest('./public/')) 後面加上

.pipe(browserSync.stream());

壓縮優化程式碼

安裝

cleanCssuglify

$ npm install --save gulp-clean-css gulp-uglify

配置 gulpfile.js

  • .pipe($.cleanCss())
  • .pipe($.uglify())
  • compress
gulp.task('sass', function () {
return gulp.src('./source/scss/**/*.scss')
.pipe($.plumber())
.pipe($.sourcemaps.init())
.pipe($.sass().on('error', $.sass.logError))
.pipe($.postcss( [autoprefixer()] ))
.pipe($.cleanCss())
.pipe($.sourcemaps.write('.'))
.pipe(gulp.dest('./public/css/'))
.pipe(browserSync.stream());
});

gulp.task('babel', () => {
return gulp.src('./source/js/**/*.js')
.pipe($.plumber())
.pipe($.sourcemaps.init())
.pipe($.babel({
presets: ['@babel/env']
}))
.pipe($.concat('all.js'))
.pipe($.uglify({
compress: {
drop_console: true
}
}))
.pipe($.sourcemaps.write('.'))
.pipe(gulp.dest('./public/js/'))
.pipe(browserSync.stream());
});

gulp.task('vendorJs', () => {
return gulp.src([
'./.tmp/vendors/**/*.js',
'./node_modules/bootstrap/dist/js/bootstrap.bundle.min.js'
])
.pipe($.order([
'jquery.js',
'bootstrap.js'
]))
.pipe($.concat('vendors.js'))
.pipe($.uglify())
.pipe(gulp.dest('./public/js/'));
});