内容简介:gulp打造前端自动化工作流
在引入gulp构建 工具 之前,我的开发方式和目录是这样的:
project
-- test 存放html文档
--0618
-- coin
-- css 存放css文档
-- web
-- app
-- app.css
-- js 存放js文档
-- web
-- app
-- scroll.js
-- image 存放image
-- web
-- app
-- logo.png
-- gitignore git忽略文件
-- node_modules grunt模块
-- gruntfile.js grunt配置文件信息
-- README.md 组件总体说明
-- package.json 版本等元信息
这样的一套开发框架结合seajs、git、switchHost、grunt和jenkins从去年5月份开始一直沿用到了今天,这样做的优势是非常简单,当开发团队很小的时候操作起来非常自由。当团队扩展速度越来越快时,所涉及到的成员由我一人到杭州+上海若干团队成员的共同参与,于是也有不少同学来向我反馈一些问题:
-
1. 老版开发模式的瓶颈
- 我手上的这个项目文件应该放在什么目录下面,需要依赖现有那些公共库?
- 前端项目开发完毕后转化为jsp/vm需要手动修改域名,能否加个配置?
- 工程量越来越大,后续维护不好弄,老的不敢删除,新的越来越多
- 每次发布上线后总是会遇到缓存问题
- 上线部署比较麻烦,需要手动发布到又拍云,项目越大越容易漏文件
我相信随着业务的发展和团队人员的扩张,每个团队都会遇到类似的问题,如何改造现有的工程,既保证业务的海海需求不会delay,同时也要提高团队成员的开发效率,就是我最近在探索的前端自动化工作流,来帮助我们前端人员开阔眼界,提升效率,让开发的归开发,让部署的归部署,解放前端生产力来做更多有意义的事情, 而不是每天苦逼的调bug,改代码,日复一日地加班。
-
2. 新版开发模式的项目需求
- 组件化的开发方式,互不影响,同时兼容现有线上公共代码;
- 开发环境工程和部署环境工程分离;
- 资源定位,通过参数配置实现线上和测试环境cdn指向区分;
- 非覆盖式发布脚本,实现程序自动化发布实现;
- 静态资源发布上线需要做压缩优化
- mock server,模拟服务端动态数据
-
3. 项目选型考察结果
fis: --优点 1.广泛使用,社区氛围浓郁,最近出了fis3 2.使用简单,容易上手; 3.国产良心; --缺点 1.黑盒,不清楚实现原理; 2.感觉插件略少,不像其他两个有npm包支持 3.速度太!慢!,realese一个工程好好久 grunt: --优点 1.最早被广泛使用的构建工具; 2.插件丰富; --缺点 1.配置麻烦; 2.速度太!慢! gulp: --优点 1.基于工作流的自动化构建工具,不生成中间文件,大大加快了构建速度; 2.插件丰富,使用广泛; 3.通过代码而非配置的形式,更适合前端开发人员使用 --缺点 学习门槛较高,需要对node较熟悉
对目前主流的自动化构建工具的考察结果,综合社区氛围、插件丰富程度、使用习惯以及构建速度来看,gulp有一定的优势,以下我们就用gulp来改造现有较为冗余的工程项目。
- 4. 先从改造项目目录开始
新版工程项目地址, 摸我
--app 负责存放工程地址(源地址)
--common 存放公共静态资源库
--js common js脚本
--libs
--公共类插件,比如validator,dialog,scroll等等,自定义的公共基础模块
--vendors
--第三方公共脚本,jQuery,zepto,seajs,template,html5,modernizr等。
--bi等
--公共类业务脚本
--style 公共样式文件
--web
--header.less
--btn.less
--view
--0818
--app view/0818/app是一个独立的模块。
css
--818.css
js
--818.js
index.html
--web
--dist 本地构建目录(目标地址)
--0818
--coin
--mock_server 本地模拟服务端数据
--data
--product.json 模拟服务端数据(18产品)
--list.json
--index.js mock_server配置信息(通过express搭建)
--node_modules node模块
--gitignore git忽略文件
--gulpfile.js gulp配置文件信息
--README.md 组件总体说明
--package.json 版本等元信息
- 5. gulpfile代码分解
1.定义模块变量
var gulp = require('gulp'); //基础,必须引入
var del = require('del'); //清理文件夹,可选
var args = require('minimist')(process.argv.slice(2)); //关键:读取传入参数,其中minimist是一个命令行插件。
//0:node,1:文件路径
var plugins = require('gulp-load-plugins')(); //通过驼峰直接读取模块而不需要require
//移动端调试
var browserSync = require('browser-sync').create(); //移动端调试神器
var url = require('url'); //解析url
2.配置参数和项目路径
//1.-n : 构建项目名称,必须带上
//2.--dist : 是否对工程进行构建(如果不构建,就启动当前项目)
//3.--production: 控制是否线上发布,可选
// 1.获取项目名称
if (!args.n) {
console.log('请使用 -n 参数设置项目名称, 比如 -n view/0818/web');
process.exit(0);
}
var projectName = args.n.toString();
// 2. 是否进行构建
//(当启动服务器的时候是在项目工程启动还是构建目录启动)
if (args.dist) args.domain = false;
// 3.控制是否线上发布
var isProduction = args.production; //获取线上版本参数
var cdn = isProduction
? 'http://wacai-file.b0.upaiyun.com'
: 'http://b1.cdn.wacaiyun.com';
//4.获取路径
//dir代表当前的目录,resolve相当于不断的调用系统的cd命令,将path一路拼接起来
var paths = {
dir : path.resolve(__dirname),
base: path.resolve(__dirname, 'app'),
dist: path.resolve(__dirname, 'dist',projectName)
};
var projPath = path.resolve(paths.base,projectName);
构建任务之
####一. 清理任务,每次构建先清理构建目录内容
gulp.task('clean', function () {
return del([paths.dist]);
});
####二. less编译任务,后续工程样式文件从.css迁入.less
//执行less任务
gulp.task('less', function () {
return gulp.src(projPath + '/**/[^_]*.less')
//plumber:任务错误中断后继续
.pipe(plugins.plumber())
.pipe(plugins.less())
.pipe(plugins.autoprefixer())
.pipe(gulp.dest(projPath));
});
//demo @import (less) "../../../common/styles/web/reset.less"; @import (less) "../../../common/styles/web/var.less"; @import (less) "../../../common/styles/web/header.less"; @import (less) "../../../common/styles/web/footer.less"; @import (less) "../../../common/styles/web/form.less"; @import (less) "../../../common/styles/web/layout.less"; @import (less) "../../../common/styles/web/btn.less"; @import (less) "../../../common/styles/web/modalBox.less"; @import (less) "./user.css";
####三. 构建任务
gulp.task('build', ['clean','less'], function (){
//revAll是一个构造方法
var revAll = new plugins.revAll({
//html不加md5
dontRenameFile: ['.html'],
dontUpdateReference: ['.html'],
//rev - revisioned reference path 调整后的路径
//source - original reference path 源路径(相对于html的路径)
//path - path to the file 文件路径(绝对路径)
transformPath: function (rev, source, file){
//如果是cdn绝对地址,不做转换
if(file.path.indexOf('//')==0) return;
//如果不是发布到dist目录,静态资源+cdn前缀
if (args.domain !== false) {
var filePath = file.path.slice(__dirname.lastIndexOf('/'))
return cdn + filePath;
}
//如果发布到dist目录,返回转化后地址
return rev;
}
});
//css,html,js筛选
var cssFilter = plugins.filter('**/*.css');
var htmlFilter = plugins.filter('**/*.html');
var jsFilter = plugins.filter('**/*.js');
return gulp.src([projPath + '/**/*.{png,jpg,html,css,js}'])
.pipe(revAll.revision())
.pipe(cssFilter)
.pipe(plugins.minifyCss())
.pipe(cssFilter.restore())
.pipe(jsFilter)
.pipe(plugins.uglify())
.pipe(jsFilter.restore())
.pipe(htmlFilter)
//conditionals:true,不移除ie浏览器相关的注释代码
.pipe(plugins.minifyHtml({conditionals: true}))
.pipe(htmlFilter.restore())
.pipe(gulp.dest(paths.dist))
//生成manifest文件
.pipe(revAll.manifestFile())
.pipe(gulp.dest(paths.dist));
});
####四. mock-server任务
//自动启动/重启你的node程序,开发node服务端程序必备
gulp.task('mock-server', function (){
plugins.nodemon({
script: './mock_server/index.js'
});
});
####五.本地服务器任务
//如果不需要构建,只需要启动下服务器就行
var preTasks = args.dist ? ['mock-server', 'build'] : ['less','mock-server'];
//启动服务
gulp.task('server', preTasks, function (){
var proxies = [];
//理财下面统一用finacne,notification是主站访问登录信息的接口
['finance', 'notification'].forEach(function (route){
//9999是express里面配置的端口
//url.parse返回url对象的属性
var proxyOption = url.parse('http://localhost:9999/' + route);
proxyOption.route = '/' + route;
proxies.push(proxy(proxyOption));
});
//browersync支持本地服务
browserSync.init({
//实时注入css,改动保存即生效
files: "**",
server: {
//baseDir必需和middleware必选
baseDir: [args.dist ? paths.dist : projPath],
middleware: proxies
},
browser: "google chrome"
});
//当css文件变动时,执行less任务
gulp.watch([projPath + '/**/*.css', projPath + '/**/*.less', paths.base + '/common/**/*.css'], ['less']);
//当js文件变动
gulp.watch([projPath + '/**/*.js', paths.base + '/common/**/*.js']);
});
####六.自动部署页面任务
//deploy:html,部署html页面
gulp.task('deploy:html', ['build'], function (cb){
var hostname = isProduction ? '192.168.11.133' : '192.168.3.185';
//rsync是1个 linux 下面同步工具
return gulp.src(paths.dist + '/**/*.html')
.pipe(plugins.rsync({
root: 'dist',
destination: '/data/program/fcactive_webapps/fcactive',
hostname: hostname,
username: 'appweb'
}));
});
####七.自动部署CDN
gulp.task('deploy:cdn', ['build'], function(cb){
if (isProduction) {
var upyun = new UPYUN('xxxx', 'xxx', 'xxx');
var files = glob.sync(paths.dist + '/**/*.{css,jpg,png,gif,js}');
var remotePath = '/finance_web';
var i = 0;
files.forEach(function(file){
var remote = remotePath + '/' + projectName.replace(/^view\//,"") + file.replace(paths.dist, '');
upyun.uploadFile(remote, file, mime.lookup(file), true, function(err, result){
if (err) console.log(err);
if (result.statusCode != 200) {
console.log(result);
}
i++;
if (i === files.length) {
console.log(i + '个资源文件被上传到又拍云CDN');
cb();
}
});
});
} else {
var hostname = '1xx.1xx.1.x';
return gulp.src(paths.dist + '/**/*.{css,js,jpg,png,gif}')
.pipe(plugins.rsync({
root: 'dist/view',
destination: '/data/program/cdnweb_branchs/b1/finance',
hostname: hostname,
username: 'appweb'
}));
}
});
- 6. 下一步计划
- seajs依赖、合并处理(use和require里面如何读取到最新增量文件);
- 开发与配置分离,目前都是通过gulpfile去控制,多人开发的时候容易弄错;
- js打包任务,是继续用seajs还是有其他的方案?
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- 前端工程工作流规范
- 前端工作流中的hooks
- 使用webpack4打造自己的前端工作流
- Gulp4 前端自动化工作流配置
- 前端工程化:围绕Jenkins打造工作流的过程
- LegoFlow 开源 v2.0 版本,前端工作流客户端
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
科技投资新时代:TMT投资方法、趋势与热点聚焦
马军、宋辉、段迎晟 / 人民邮电出版社 / 2018-3 / 69.00
中国 TMT 行业(科技、媒体及通信)起步较晚但充满朝气。2017 年,TMT 板块的IPO 数量占到了总数的四分之一;对于投资者来说,投资 TMT 的收益非常可观。那么,TMT 的投资趋势如何? TMT 行业又有哪些投资热点? 本书立足于 TMT 投资现状,在介绍了 TMT 投资的基本概念之后,作者详细讲述了TMT 投资的基本研究方法、分析视角、整体行情及趋势分析,同时从行业视角分析了包括......一起来看看 《科技投资新时代:TMT投资方法、趋势与热点聚焦》 这本书的介绍吧!