本次打包大體過程是checkout出想要打包的git版本(能夠是tag,也能夠是branchName),而後依次讀取項目中的html、less、js進行壓縮合並等操做,複製項目中所用到的第三方庫到輸出目錄(即plugins中的插件,好比lodash、echarts等,前邊壓縮合並的js是本身寫的js),而後打zip包,發送至目的地。
css
在gulp腳本中聲明下載的gulp插件,即:html
var gulp = require('gulp'), concat = require('gulp-concat'), less = require('gulp-less'), minifyCss = require('gulp-minify-css'), minify = require('gulp-minify'), zip = require('gulp-zip'), moment = require("moment"), ftp = require('gulp-ftp'), git = require('gulp-git'), runSequence = require('run-sequence'), argv = require('minimist')(process.argv.slice(2)), del = require('del'), uglify = require('gulp-uglify'), htmlmin = require('gulp-htmlmin'), ngAnnotate = require('gulp-ng-annotate');
好比項目結構圖以下:
那麼這裏配置的輸入輸出路徑即爲:
路徑以gulpfile.js爲參考位置。git
var path={ input:{ html:['src/app/*.html'], js:['src/app/js/*.js'], less:['src/app/less/*.less'], image:['src/app/image/*'], fonts:['src/app/fonts/*'], plugins:['src/plugins/**/*'] } output:{ dist:'dist', plugins:'dist/plugins' } }
若是不想要某文件,好比不想去壓縮html1.htmlgulp
var path={ input:{ html:['src/app/*.html','!src/app/html1.html'], } }
'!'後面也能夠跟某一類型文件,或者直接指定某文件夾。segmentfault
若是想打包git版本庫中的某一個版本,或者某一個分支,就須要用到git.checkout,可是在checkout以前,須要首先提交git版本,若是在git-bash下,會進行以下操做。bash
git add . git commit -m 「there are some comments」
在gulp中也同樣,咱們須要編寫以下代碼服務器
gulp.task('commit', function(){ return gulp.src('./demo/**/*') .pipe(git.add()) .pipe(git.commit()); });
commit的必要性是若是在本地工做空間修改,而沒有提交到本地倉庫的話,代碼有可能會丟。
上面這段代碼也能夠不寫,不寫的話,就須要每次執行gulp腳本以前,手動commit一下,總之,commit很重要。。。app
接下來,就要checkout出相關版本了,由於不能肯定打那個一版本的包,全部這裏可能須要用命令行手動去指定一個版本,這裏就用到了上篇提到的一個插件,minimist,插件具體就不在介紹了,這裏直接上checkout的代碼。echarts
gulp.task('checkout',[commit], function () { gitTag = argv.tag; git.checkout(gitTag, function (err) { if (err) throw err; }); })
其中argv.tag就是用了minimist獲取的,命令行我會這樣輸入。less
gulp publish --tag v1.0.0
這種是指定tag的方式,還能夠給gitTag 變量加一個默認值,即
gitTag = argv.tag||defaultValue;
這個defaultValue能夠寫死一個版本,也能夠在每次commit的時候生成一個tag,gulp-git也有creat-tag的功能,這個方案我是沒有去嘗試的,理論上應該沒啥問題,沒有去用的主要緣由是,感受這樣打的tag有點多了,因此仍是手動去給一個tag。
到這裏,已經能夠取出咱們要打包的項目代碼了,下面開始進行具體打包工做。
壓縮合並,簡單來講,就是指定須要處理的資源,而後調用相關函數,輸出到某目錄,等待下一步處理。
這裏難度不大,直接上代碼:
壓縮html
gulp.task('html', function () { var options = { removeComments: true, collapseWhitespace: true, collapseBooleanAttributes: true, removeEmptyAttributes: true, removeScriptTypeAttributes: true, removeStyleLinkTypeAttributes: true, minifyJS: true, minifyCSS: true }; return gulp.src(config.input.html) .pipe(htmlmin(options)) .pipe(gulp.dest(config.output.dist))//gulp dest是輸出 });
壓縮合並JS
gulp.task('js', function (done) { return gulp.src(config.input.js) .pipe(ngAnnotate({single_quotes: true})) .pipe(uglify()) .pipe(concat('index.min.js')) .pipe(gulp.dest(config.output.dist)) });
編譯壓縮合並less
gulp.task('less', function () { return gulp.src(config.input.less) .pipe(less()) .pipe(minifyCss()) .pipe(concat('index.min.css')) .pipe(gulp.dest(config.output.dist)); });
複製第三方插件
gulp.task('copy', function (done) { return gulp.src(config.input.plugins) .pipe(gulp.dest(config.dist.plugins); });
正常狀況進行過上面4步操做最後,會獲得這樣的結果:
通過合併壓縮等操做以後,項目會自動生成dist目錄,dist目錄下即爲打包生成的各類文件,接下來的目標是將dist目錄下的全部文件打成一個zip包,代碼以下:
gulp.task('zip_new', function () { var timeStamp = moment().format("YYYY-MM-D_HH-mm-ss_"); return gulp.src(config.input.zip) .pipe(zip("dist_" + timeStamp + ".zip")) .pipe(gulp.dest(config.output.dist)); });
moment是一個獲取時間的插件,能夠給打的包一個時間來標記,這個加不加都無所謂,zip方法裏面就是zip包的名稱,隨意命名。
將zip包打好以後即可以發送zip包到某服務器了,代碼以下:
gulp.task('ftp', function () { gulp.src("dist_zip/*") .pipe(ftp({ host: 'someHost', port: 21, //user: 'anonymous', //pass:null, remotePath: "somePath/" })); });
至這裏,打包就所有完成了,下面要作的就是把他們連起來,這裏用到上篇提到的插件,run-sequence,插件用法以下:
gulp.task('publish', function (callback) { runSequence(['html', 'js','less', 'copy'],'zip_new',ftp,callback); });
這裏有兩點須要注意:
1.run-sequence裏面的任務,按順序執行(方括號裏面4個任務,算做一個任務),並且前一個跑完纔會跑後一個,方括號裏的是異步的,即不必定哪一個先完成。
2.要想達到第一點裏面的同步執行(一個任務完成纔開始下一個),必定要保證前面的全部任務,即除了ftp任務,其他的方法必定要是return出來的,即:
<font color=#20B2AA size=4>正確寫法:</font>
gulp.task('js', function (done) { return gulp.src(config.input.js) .pipe(ngAnnotate({single_quotes: true})) .pipe(uglify()) .pipe(concat('index.min.js')) .pipe(gulp.dest(config.output.dist)) });
<font color=#DC143C size=4>錯誤寫法:</font>
gulp.task('js', function (done) { gulp.src(config.input.js) .pipe(ngAnnotate({single_quotes: true})) .pipe(uglify()) .pipe(concat('index.min.js')) .pipe(gulp.dest(config.output.dist)) });
前邊都要這樣寫,最後一項不加return,在本例中,即ftp的方法不用返回。
寫到這裏,還有一個問題,就是沒有對文件夾進行清理,這也是比較重要的,在每一次開始打包工做以前,咱們須要清理dist目錄,以保證下一次打包不會被上一次打包的文件「污染」。這裏用到gulp-del的插件,代碼以下:
gulp.task('clean',function(){ return del(config.output.dist); })
通過以上,一個完整的run-sequence以下:
gulp.task('publish', function (callback) { runSequence('clean','checkout',['html', 'js','less', 'copy'],'zip_new','ftp',callback); });
流程圖: