使用gulp實現前端自動化

CL2發表於2018-12-12

gulp是一個自動化構建工具,開發者可以用它來自動執行一些常見的任務。這裡以我之前做的一個demo為例,簡要介紹如何使用gulp實現前端工程自動化。

專案結構

使用gulp實現前端自動化

其中src目錄下表示的是專案的原始碼,可以看到其中有less、js、html等,而dist目錄則是儲存的是gulp編譯後生成的程式碼,相當於生產環境。最後也最重要的是gulpfile.js,這個檔案用於設定gulp相關的配置,類似於webpack中的webpack.config.js

安裝

這裡使用的gulp為v3.9.1,語法和最新的v4.x有所出入,想學習最新的gulp語法,可以參考gulp.js - The streaming build system

3.9.1 安裝如下:

npm install --save-dev gulp
複製程式碼
語法
  • gulp.task()用於定義一個gulp任務,在命令列中可以使用gulp [任務名]開啟該任務。
  • gulp.src()會返回符合匹配的檔案流,可以被pipe()到其他外掛中。
  • gulp.dest():輸出所有資料。
  • gulp.watch()用於監測檔案的變動。
實踐

在這個專案中,有一些常見的需求,這裡使用gulp來實現自動化:

  • less轉css
  • css壓縮合並
  • js壓縮合並
  • 圖片壓縮

gulpfile.js中首先需要匯入gulp和一些常用的外掛,本次demo使用到的外掛如下:

var gulp = require('gulp'),
    less = require('gulp-less'),                   //less 轉 css
    csso = require('gulp-csso'),                   //css壓縮
    concat = require('gulp-concat'),               //合併檔案
    uglify = require('gulp-uglify'),               //js 壓縮
    jshint = require('gulp-jshint'),               //js 檢查
    clean = require('gulp-clean'),                 //清除檔案
    imagemin = require('gulp-imagemin'),           //圖片壓縮
    rev = require('gulp-rev'),                     //新增版本號
    revReplace = require('gulp-rev-replace'),      //版本號替換
    useref = require('gulp-useref'),               //解析html資源定位
    gulpif = require('gulp-if'),                   //if語句
    connect = require('gulp-connect');             //建立web伺服器
複製程式碼
圖片壓縮

獲取到src下所有以.jpg.png結尾的圖片,將其壓縮後輸出到dist目錄下。

gulp.task('dist:img', () => {
    gulp.src(['./src/**/*.jpg', './src/**/*.png'])
    .pipe(imagemin())
    .pipe(gulp.dest('dist/'))
})
複製程式碼
less壓縮合併為css

先清除已存在的css,然後將src下以.less結尾的檔案通過less()轉為css檔案,再通過csso()以及concat()實現對css的壓縮合並。

gulp.task('dist:css', () => {
    gulp.src('dist/css/*.css').pipe(clean());
    return gulp.src('./src/less/*.less')
    .pipe(less())
    .pipe(csso())
    .pipe(concat('public.css'))
    .pipe(gulp.dest('dist/css/'));
});
複製程式碼
js壓縮合並

js壓縮合並的過程大同小異,增加了一個jshint()程式碼審查的過程,它會將不符合規範的錯誤程式碼輸出到控制檯。

gulp.task('dist:js', () => {
    gulp.src('dist/js/*.js').pipe(clean());
    return gulp.src('./src/js/*.js')
    .pipe(jshint())
    .pipe(jshint.reporter('default'))
    .pipe(uglify())
    .pipe(concat('public.js'))
    .pipe(gulp.dest('dist/js/'))
});
複製程式碼
less轉css

在開發過程中,因為html不能直接引入.less檔案,因此還需要生成開發環境的.css

gulp.task('src:css', () => {
    gulp.src('src/css/*.css').pipe(clean());
    return gulp.src('./src/less/*.less')
    .pipe(less())
    .pipe(gulp.dest('src/css/'));
});
複製程式碼
新增版本號

為了防止瀏覽器對檔案進行快取,需要對檔案新增版本號,保證每次獲取到的都是最新的程式碼。

gulp.task('revision', ['dist:css', 'dist:js'], () => {
    return gulp.src(["dist/css/*.css", "dist/js/*.js"])
    .pipe(rev())
    .pipe(gulpif('*.css', gulp.dest('dist/css'), gulp.dest('dist/js')))
    .pipe(rev.manifest())
    .pipe(gulp.dest('dist'))
})
gulp.task('build', ['dist:img'], () => {
    var manifest = gulp.src('dist/rev-manifest.json');
    return gulp.src('src/index.html')
    .pipe(revReplace({
        manifest: manifest
    }))
    .pipe(useref())
    .pipe(gulp.dest('dist/'))
})
複製程式碼

revision中,首先通過rev()dist目錄下的.css/.js生成一個檔名帶版本號的檔案,例如本例中public.css生成public-5c001c53f6.css,然後分別輸出到不同的目錄下,最後生成一個rev-manifest.json檔案,儲存了原檔案和帶版本號檔案之間的對映關係,如下:

{
  "public.css": "public-5c001c53f6.css",
  "public.js": "public-93c275a836.js"
}
複製程式碼

build中,先獲取到rev-manifest.json中的物件,然後利用revReplace()來替換版本號,再使用useref()來進行資源的解析定位,最後輸出即可。

以引入js檔案為例,源html檔案中對檔案的引入則要改寫為以下形式,即以註釋的形式寫入構建後生成的檔案路徑,如下:

<!-- build:js ./js/public.js -->
<script src="./js/jquery-1.12.4.min.js"></script>
<script src="./js/myAlbum.js"></script>
<!-- endbuild -->
複製程式碼

最後生成的html為:

<script src="./js/public-93c275a836.js"></script>
複製程式碼

具體的語法規則可以參見gulp-useref

建立本地伺服器並實現自動重新整理

使用connet.server()來建立一個本地伺服器,利用gulp.watch()來對src下的檔案進行監測,如果發生變化,則執行編譯lesscss和重新整理頁面的任務。

gulp.task('connect', () => {
    connect.server({
        root: 'src',
        livereload: true,
        port: 8888
    })
})
gulp.task('reload', () => {
    gulp.src('src/*.html')
    .pipe(connect.reload())
})
gulp.task('watch', () => {
    gulp.watch('src/**/*', ['src:css', 'reload'])
})
複製程式碼

完整的程式碼可以參見github

原文地址:

相關文章