前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >gulp+webpack工作流探索

gulp+webpack工作流探索

作者头像
Ganother
发布2019-02-26 10:40:44
1.3K0
发布2019-02-26 10:40:44
举报
文章被收录于专栏:SylvanasClubSylvanasClub

概述

最近研究了下工作流,先说一下我司的情况,我司现在是pc端用php直出,h5用vuejs构建,vuejs部分就不进行描述了,因为网上的构建方法都是很成熟的了。 以下是php直出,需要向后台同学提供html文件的构建方法。调试都是在本地调试的,调试完成后打包生成html交付给后台同学。

http-server 模拟数据,调试ajax

webpack 打包js,模块化管理

gulp打包css,压缩css, 压缩图片

项目目录

|- 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中的引用,所以在网上找到了一个方法。

打开node_modulesgulp-revindex.js

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

打开nodemodulesgulp-revnodemodulesrev-pathindex.js

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

打开node_modulesgulp-rev-collectorindex.js

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如下

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,这样每次打包的时候就不用把整个项目都打包了,只打包需要打包的项目。

合并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执行的情况,有条件的,还是弄个开发机来调试比较好。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2016-08-05,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 概述
  • 项目目录
  • 修改依赖包内容
  • gulp打包
    • 按需打包
      • webpack配置
      • 模拟数据
      • 总结
      相关产品与服务
      内容分发网络 CDN
      内容分发网络(Content Delivery Network,CDN)通过将站点内容发布至遍布全球的海量加速节点,使其用户可就近获取所需内容,避免因网络拥堵、跨运营商、跨地域、跨境等因素带来的网络不稳定、访问延迟高等问题,有效提升下载速度、降低响应时间,提供流畅的用户体验。
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档