gulp+webpack工做流探索

概述

最近研究了下工做流,先說一下我司的狀況,我司如今是pc端用php直出,h5用vuejs構建,vuejs部分就不進行描述了,由於網上的構建方法都是很成熟的了。
如下是php直出,須要向後臺同窗提供html文件的構建方法。調試都是在本地調試的,調試完成後打包生成html交付給後臺同窗。javascript

http-server 模擬數據,調試ajaxphp

webpack 打包js,模塊化管理css

gulp打包css,壓縮css, 壓縮圖片html

項目目錄

|- apps //html文件  
|- dist  
    |- css //存放壓縮打包後的css  
    |- js //webpack 自動打包的js  
    |- images //壓縮後的圖片  
    //這裏還有打包後的html文件  
|- mock //模擬數據,json  
|- ssi //生成的ssi頁面片  
|- js //js源文件  
    |- common 公共模塊  
    |- 業務js  
|- css   
    |- sass //sass源文件  
        |- common 公共sass函數  
        |- 業務css  
    |- stylesheets //編譯後的css 開發時引入 compass編譯  
|- images  
    原圖片

修改依賴包內容

由於rev默認生成的版本號是加在靜態文件文件名上的,如main-d3id7340.js這樣會形成服務器上有n多的js,因此咱們但願生成main.js?v=233333這樣的版本號,在配合ssi就能很好的維護,之後若是隻涉及修改靜態文件的時候,就只用從新上傳靜態文件和ssi頁面片就能夠了,不須要再去改php中的引用,因此在網上找到了一個方法。vue

打開node_modulesgulp-revindex.jsjava

第133行 manifest[originalFile] = revisionedFile;
更新爲: manifest[originalFile] = originalFile + '?v=' + file.revHash;

打開nodemodulesgulp-revnodemodulesrev-pathindex.jsnode

10行 return filename + '-' + hash + ext;
更新爲: return filename + ext;

打開node_modulesgulp-rev-collectorindex.jsjquery

31行 if ( path.basename(json[key]).replace(new RegExp( opts.revSuffix ), '' ) !== path.basename(key) ) {
更新爲: if ( path.basename(json[key]).split('?')[0] !== path.basename(key) ) {

gulp打包

gulpfile.js以下webpack

var gulp = require('gulp');
var minicss = require('gulp-cssmin');
var useref = require('gulp-useref');
var imagemin = require('gulp-imagemin');
var pngquant = require('imagemin-pngquant');
var gulpif = require('gulp-if');
var yargs = require('yargs');
var rev = require("gulp-rev");
var revCollector = require("gulp-rev-collector");
var replace = require("gulp-replace");
var runSequence = require('run-sequence');

var output = "dist";
//獲取輸入的參數
var argv = yargs.argv,
  name = argv.name,
  type;

if(argv.type == "pub"){
  type = "";
}else if(argv.type == "test"){
  type = ".test"
}

//合併html裏用到的css
gulp.task('csscombine',function(){
  return gulp.src('apps/'+name+'/*')
    .pipe(useref())
    .pipe(gulpif('*.css', minicss()))
    .pipe(gulp.dest("dist"));

});

//壓縮css,生成css版本號
gulp.task('css', function(){
  return gulp.src('dist/css/'+name+'/*.css')
    .pipe(rev())
    .pipe(gulp.dest('dist/css/'+name))
    .pipe( rev.manifest() )
    .pipe( gulp.dest( 'rev/css' ) );
});

//生成js版本號
gulp.task('js', function(){
  return gulp.src('dist/js/'+name+'/*.js')
    .pipe(rev())
    .pipe(gulp.dest('dist/js/'+name))
    .pipe( rev.manifest() )
    .pipe( gulp.dest( 'rev/js' ) );
});

//壓縮圖片
gulp.task("imagemin", function(){
  return gulp.src('images/'+name+'/*')
    .pipe(imagemin({
      progressive: true,
      svgoPlugins: [{removeViewBox: false}],
      use: [pngquant()]
    }))
    .pipe(gulp.dest(output + '/images/'+name));
})

//生成cssi頁面片
gulp.task("cssi",function(){
  return gulp.src(['rev/**/*.json','ssi/cssi/cssi.html'])
  .pipe(replace('{name}',name))
  .pipe(replace('{type}',type))
  .pipe( revCollector())
  .pipe(gulp.dest("ssi/cssi/"+name));
});

//生成jsi頁面片
gulp.task("jsi", function(){
  return  gulp.src(['rev/**/*.json','ssi/jsi/jsi.html'])
    .pipe(replace('{name}',name))
    .pipe(replace('{type}',type))
    .pipe( revCollector())
    .pipe(gulp.dest("ssi/jsi/"+name));
});

//替換html裏的路徑
gulp.task("replacehtml",function(){
  var scriptReg = new RegExp("<script src.+"+name+".+script>","g");
  var scriptResult = '<!--#include virtual="/ssi/jsi/'+name+'/jsi.html" -->';
  var cssReg = new RegExp("<link .+ href=.+"+name+".+>","g");
  var cssResult = '<!--#include virtual="/ssi/cssi/'+name+'/cssi.html" -->';
  return gulp.src('dist/'+name+'.html')
    .pipe(replace(scriptReg,scriptResult))
    .pipe(replace(cssReg,cssResult))
    .pipe(replace('../../images/'+name+'/','//assets'+type+'.cm233.com/dist/images/'+name+'/'))
    .pipe(gulp.dest("dist"))
});

//主函數,打包
gulp.task('package', function() {

  if(!argv.name){
    console.log("請輸入打包項目");
    return ;
  }
  if(!argv.type){
    console.log("請輸入打包類型! pub-發佈 test-測試");
    return ;
  }

  runSequence('csscombine',
    ['css','js','imagemin'],
    ['cssi','jsi'],
    'replacehtml',
    function(){
      console.log("打包成功")
    });


});

按需打包

與網上一些不一樣的是,這個要求開發者輸入參數name和type,這樣每次打包的時候就不用把整個項目都打包了,只打包須要打包的項目。nginx

合併css部分,須要在html裏作下處理

<!-- build:css css/cm_share_h5/cm_share_h5.css -->
 <link type="text/css" rel="stylesheet" href="../../css/stylesheets/main.css">
  <link type="text/css" rel="stylesheet" href="../../css/stylesheets/detail.css">
  <!-- endbuild -->

生成ssi部分,要先建立模板文件,根據壓縮css和js時生成的版本號,把相應的名字和版本號替換掉,而後在html裏把引用腳本的路徑改成ssi引用便可

<link rel="stylesheet" href="//assets{type}.ganother.com/dist/css/{name}/{name}.css">

webpack配置

webpack.config.js,僅用於處理js模塊依賴

var webpack = require('webpack');
var fs = require('fs');
var path = require("path");
var srcDir = './'

function getEntry() {
  var jsPath = path.resolve(srcDir, 'js/page');
  var dirs = fs.readdirSync(jsPath);
  var matchs = [], files = {};
  dirs.forEach(function (item) {
    matchs = item.match(/(.+)\.js$/);
    if (matchs) {
      files[matchs[1]] = path.resolve(srcDir, 'js/page', item);
    }
  });
  return files;
}

module.exports = {
  devtool: "source-map",    //生成sourcemap,便於開發調試
  entry: getEntry(),         //獲取項目入口js文件
  output: {
    path: path.join(__dirname, "dist/js"), //文件輸出目錄
//    publicPath: path.join("dist/js/"),        //用於配置文件發佈路徑,如CDN或本地服務器
    filename: "[name]/[name].js",        //根據入口文件輸出的對應多個文件名
  },
  module: {
    //各類加載器,即讓各類文件格式可用require引用
    loaders: [
       { test: /\.js$/, loader: "babel"},
    ]
  },
  resolve: {
    //配置別名,在項目中可縮減引用路徑
    alias: {
      jquery: path.resolve(srcDir, "dist/js/lib/jquery-1.12.4.min.js"),
      module: path.resolve(srcDir, "js/module")
    }
  },
  externals: {
    // require("jquery") is external and available
    //  on the global var jQuery
    "jquery": "jQuery"
  },
  plugins: [
    //js文件的壓縮
    new webpack.optimize.UglifyJsPlugin({
      compress: {
        warnings: false
      }
    })
  ]
};

模擬數據

http-server能夠用項目目錄生成的url模擬ajax請求(只有get),直接把json放在裏面,而後根據項目目錄的url就能夠訪問。可是交付的時候要記得換掉url,其實也能夠自動化一下,要與後臺約定好目錄結構,而後打包的時候用gulp替換。

總結

在思考工做流的時候,思考最多的就是如何在php直出而且由後端同事寫模版文件的狀況下作好交付html和後期脫離後端同事進行靜態文件維護,好像除了用nginx ssi沒什麼其餘好辦法再不改模版文件的狀況下更換靜態文件(由於要加時間戳防止緩存)。本地調試仍是有不少不科學的地方,好比模擬數據這裏,可能更換成真實接口的數據會出現其它的意外狀況,填充模版後也可能會出現影響js執行的狀況,有條件的,仍是弄個開發機來調試比較好。

相關文章
相關標籤/搜索