基于 gulp 的前端自动化构建方案总结
(一)演示项目目录结构
|-testProject (项目名称)
|–.git 通过git进行版本控制,项目自动生成这个文件
|–node_modules 插件包目录
|–dist **发布环境**(编译自动生成的)
|–css 样式文件(style.css style.min.css)
|–img 图片文件(压缩图片\合并后的图片)
|–js js文件(main.js main.min.js)
|–index.html 静态页面文件(压缩html)
|–src **开发环境**
|–css sass文件
|–img 图片文件
|–js js文件
|–index.html 静态文件
|–gulpfile.js gulp配置文件
|–package.json 依赖模块json文件,在项目目录下执行 npm install 会安装项目所有的依赖模块,方便自动化构建方案在项目之间的的快速复用
可以使用淘宝的 npm 镜像来代替官方版本(镜像同步频率目前为 10分钟 一次以保证尽量与官方服务同步)。
淘宝镜像使用方法;
- 安装 cnpm 插件:
npm install -g cnpm --registry=https://registry.npm.taobao.org
然后就可以用
cnpm
命令从淘宝镜像获取插件包了;当然,你这时候依旧可以用npm
命令从官方服务获取插件包。
cnpm
支持除 publish 之外的原生 npm 所有命令。
(二)配置 gulp 自身
请先安装 nodejs(自带 npm)环境。
下面开始进行基于 gulp 的自动化构建方案的配置:
-
在 CLI 中切换到项目目录(例如:
cd d:/wamp/www/
),执行命令:npm init
(中间会需要你填写一些信息,如果嫌烦的话,可以全部回车确认过掉),最后将生成一个package.json
文件(依赖模块json文件,在项目目录下执行 npm install 会安装项目所有的依赖模块,方便++自动化构建方案在项目之间的的快速复用++)。 -
Install gulp globally.
全局安装 gulp (如果之前进行过 gulp 全局安装,请运行
npm rm --global gulp
以确保旧版本的 gulp 不与 gulp-cli 相冲突)
$ npm install --global gulp-cli
- Install gulp in your project devDependencies
项目的开发依赖中安装 gulp
$ npm install --save-dev gulp
- 在项目根目录创建一个
gulpfile.js
文件
var gulp = require('gulp');
gulp.task('default', function() {
// place code for your default task here
});
- 至此,gulp 本身已经配置好了。可以尝试运行以下命令:
$ gulp
这将运行默认任务,但目前默认任务是空的,所以实际效果是什么也不干。
如果要运行某个具体的任务(task), 请使用 gulp <task> <othertask>
。
- 现在你拥有一个空的
gulpfile.js
并且所有东西都已经安装。那么怎样才能真正地开始呢?
请查看 recipes(方法、秘诀、食谱) 和 一系列文章 获取更多信息。
- 如何使用 API:API 文档
- 插件:gulp 社区正在不断成长,每天都有新的插件提交(截至 20160603 有2438个插件)。查看 main website 以获取完整的插件列表。
(三)安装插件
需要意识到的是:以下这些插件都是次要的,它们对应的功能才是最重要的,因为一种功能可以对应无数种插件。问题是,如何找到对应某种功能的最好用的插件。
而使用插件的思路应该是:根据项目中的实际需求 把各个插件串联起来完成一个大任务
参考:
快速安装:引入以下这个 package.json 文件,并运行
npm install
(如果安装了cnpm,也可以用 cnpm)。
{
"name": "erp",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "jialiangF",
"license": "ISC",
"devDependencies": {
"browser-sync": "^2.12.12",
"gulp": "^3.9.1",
"gulp-autoprefixer": "^3.1.0",
"gulp-cache": "^0.4.5",
"gulp-clean": "^0.3.2",
"gulp-clean-css": "^2.0.9",
"gulp-concat": "^2.6.0",
"gulp-imagemin": "^3.0.1",
"gulp-plumber": "^1.1.0",
"gulp-rename": "^1.2.2",
"gulp-sass": "^2.3.1",
"gulp-sourcemaps": "^1.6.0",
"gulp-uglify": "^1.5.3",
"gulp.spritesmith": "^6.2.1",
"imagemin-pngquant": "^5.0.0"
},
"dependencies": {}
}
1. gulp-sass
功能:把 sass 编译为 css
npm 插件文档:https://www.npmjs.com/package/gulp-sass
安装:npm install --save-dev gulp-sass
用法:
2. gulp-clean-css
功能:压缩(minify) css 文件(这里只是压缩,但后面还需要用别的插件来重命名为 xxx.min.css 的形式)
npm 插件文档:https://www.npmjs.com/package/gulp-clean-css
安装:npm install --save-dev gulp-clean-css
用法:
3. gulp-autoprefixer
这里需要考虑你的项目需要兼容到哪些版本的浏览器,然后调用的使用配置一下参数即可。
功能:为 css 属性添加浏览器前缀,同时也会自动删除一些不必要的浏览器前缀(这有点惊喜~)
npm 插件文档:https://www.npmjs.com/package/gulp-autoprefixer,
github 上的文档更详细一些:https://github.com/postcss/autoprefixer#options
安装:npm install --save-dev gulp-autoprefixer
用法:(暂时不知道比较好的配置方案,先这样)
.pipe(autoprefixer({
browsers: ['> 1%', 'not ie <= 8']
}))
4. gulp-uglify
这个插件使用的是 uglify 引擎
功能:压缩(optimize)js 文件(这里只是压缩,但后面还需要用别的插件来重命名为 xxx.min.js 的形式)
npm 插件文档:https://www.npmjs.com/package/gulp-uglify
安装:npm install --save-dev gulp-uglify
用法:
5. gulp-concat
功能:合并文件。我们可以用它来合并js或css文件等,这样就能减少页面的http请求数了
npm 插件文档:https://www.npmjs.com/package/gulp-concat
安装:文档没写...那就按照惯例作为项目的开发依赖来安装吧~
用法:
6. gulp-rename
功能:重命名文件(咚门:用过之后,发现并不能很好地满足我最初的需求:“可以批量处理,自动在 原文件名 基础上插入一个‘.min’”。非常死板,无法批量处理,只能具体文件具体重命名)
npm 插件文档:https://www.npmjs.com/package/gulp-rename
安装:文档没写...那就按照惯例作为项目的开发依赖来安装吧~
用法:
7. gulp-imagemin
gulp-imagemin的使用比较复杂一些,而且它本身也有很多插件,建议去它的项目主页看看文档(不过,文档中也说了:默认的插件自带了良好的默认配置,并且在大多数情况下足够用)
功能:压缩图片
npm 插件文档:https://www.npmjs.com/package/gulp-imagemin
安装:npm install --save-dev gulp-imagemin
用法:
8. gulp.spritesmith(注意:不是 gulp-spritesmith)
在这里我真的要废话两句,因为我真的要发火了。npm 允许开发者自由随意命名有时候真的是让人很不爽,就以这个插件为例,我 TM 的真的围着不知道那个贱*发布的 gulp-spritesmith 转了半天,这“半天”不是中国人玄学上的半天,是 12 小时是真的半天,各种请教,各种试,各种补救,最后才发现压根儿就装错了插件包!!!(不只是名字极像,语法都学得有模有样,这个贱*插件最后一次更新是两年前,现在是基本上是没法用的,但每个月都有几百个像我这样的傻逼傻傻地上当,只能为后来者默默祈祷了)
功能:生成 sprite 图
npm 插件文档:https://www.npmjs.com/package/gulp.spritesmith
安装:npm install --save-dev gulp.spritesmith
用法:
9. gulp-cache
功能:A temp file based caching proxy task for gulp.基于临时文件的缓存代理任务
npm 插件文档:https://www.npmjs.com/package/gulp-cache
安装:文档没写...那就按照惯例作为项目的开发依赖来安装吧~
用法:
10. browser-sync(貌似需要全局安装才行)
功能:自动刷新
npm 插件文档:https://www.npmjs.com/package/browser-sync
官方 API 文档:https://www.browsersync.io/docs/api
安装:文档没写...那就按照惯例作为项目的开发依赖来安装吧~
用法:
11. gulp-clean
功能:删除文件和文件夹
npm 插件文档:https://www.npmjs.com/package/gulp-clean
安装:npm install --save-dev gulp-clean
用法:
12. gulp-plumber
功能:避免因错误而中断 gulp
npm 插件文档:https://www.npmjs.com/package/gulp-plumber
安装:npm install --save-dev gulp-plumber
用法:
var plumber = require('gulp-plumber');
var coffee = require('gulp-coffee');
gulp.src('./src/*.ext')
.pipe(plumber())
.pipe(coffee())
.pipe(gulp.dest('./dist'));
13. gulp-sourcemaps
需要注意的是在
sourcemaps.init()
和sourcemaps.write()
之间的插件必须要支持gulp-sourcemaps
。可以通过 Plugins with gulp sourcemaps support 查看你所用的插件是否支持gulp-sourcemaps
。
尝试了一下,发现原来压缩之后的文件大小为 667 Bytes,使用了这个插件之后大小为 4.17 KBytes。当然,这里所用的例子文件太小,不一定具有多大的代表性,但用了这个插件之后文件大小问题确实促使我们进一步权衡需不需要用这个插件。(就我们公司目前状况来说,项目未稳定之前可能需要这个插件帮助 debug,但稳定之后就可以在配置文件中把这个插件注释掉了。)
-
功能:大部分源码都要经过转换(也就是编译、合并、压缩之类),才能投入生产环境。这使得实际运行的代码与开发代码不同,debug 变得困难重重。source map就是一个信息文件,里面储存着位置信息,也就是说,转换后的代码的每一个位置,对应的转换前的位置。有了它,debug 的时候,debug 工具将直接显示原始的开发代码,而不是转换后的代码。
-
安装:文档没写...那就按照惯例作为项目的开发依赖来安装吧~
-
用法:
var gulp = require('gulp');
var plugin1 = require('gulp-plugin1');
var plugin2 = require('gulp-plugin2');
var sourcemaps = require('gulp-sourcemaps');
gulp.task('javascript', function() {
gulp.src('src/**/*.js')
.pipe(sourcemaps.init())
.pipe(plugin1())
.pipe(plugin2())
.pipe(sourcemaps.write())
.pipe(gulp.dest('dist'));
});
(四)配置任务
在 gulpfile.js 中引入并设置任务(task)
var gulp = require('gulp');
var sass = require('gulp-sass');
var cleanCss = require('gulp-clean-css');
var autoprefixer = require('gulp-autoprefixer');
var uglify = require('gulp-uglify');
var concat = require('gulp-concat');
var rename = require('gulp-rename');
var clean = require('gulp-clean');
var sourcemaps = require('gulp-sourcemaps');
var plumber = require('gulp-plumber');
var imagemin = require('gulp-imagemin');
var pngquant = require('imagemin-pngquant');
var spritesmith = require('gulp.spritesmith');
var cache = require('gulp-cache');
var browserSync = require('browser-sync');
var reload = browserSync.reload;
// 样式文件处理(包括:编译 sass,合并 css,重命名,压缩,添加浏览器前缀,制作 sourcemaps,迁移到发布环境)
// ===============================================================================================
// 编译 scss 文件
gulp.task('sass', function(cb) { // 传入一个回调函数,因此引擎可以知道何时它会被完成
// return a value as the completion hint
return gulp.src('src/css/sass/**/*.scss')
.pipe(plumber())
// .pipe(sourcemaps.init())
.pipe(sass())
.pipe(gulp.dest('src/css/sass/tmp'))
.pipe(concat('zz-all-sass.css'))
// .pipe(gulp.dest('src/css/sass/tmp'))
// .pipe(rename('all.min.css'))
// .pipe(cleanCss())
.pipe(autoprefixer({
browsers: ['> 1%', 'not ie <= 8']
}))
// .pipe(sourcemaps.write())
.pipe(gulp.dest('src/css'));
console.log('sass 文件处理完毕!');
cb(err); // 如果 err 不是 null 和 undefined,流程会被结束掉,'two' 不会被执行
});
gulp.task('css', ['sass'], function(cb) { // 标注一个依赖,依赖的任务必须在这个任务开始之前被完成
return gulp.src('src/css/*.css')
.pipe(concat('all.min.css'))
.pipe(cleanCss())
.pipe(gulp.dest('dist/css'));
console.log('css 文件处理完毕!');
cb(err);
});
// 执行所有样式相关任务,并且开启监视
gulp.task('css-watch', ['css'], function() {
console.log('正在监视 scss 及 css 文件变动');
// 监听 sass
var watcher = gulp.watch('src/css/sass/**/*.scss', ['css']); // 监视那些文件的变动,以及变动之后执行的任务
watcher.on('change', function(event) {
// 在 CLI 中输出一些提示信息,帮助我们了解程序发生了什么
// console.log('File ' + event.path + ' was ' + event.type + ', running tasks...');
console.log('事件路径: ' + event.path + ' 事件类型: ' + event.type + ', 正在执行的任务:style');
});
});
// 压缩 JS
// =======
gulp.task('js-optimize', function(cb) {
return gulp.src('src/js/*.js')
// .pipe(sourcemaps.init())
.pipe(concat('all.js'))
.pipe(gulp.dest('dist/js/tmp'))
.pipe(rename('all.min.js'))
.pipe(uglify())
// .pipe(sourcemaps.write())
.pipe(gulp.dest('dist/js'));
console.log('js 文件优化处理完毕!');
cb(err);
});
gulp.task('js', ['js-optimize'], function(cb) {
gulp.src('src/js/others/*.js')
.pipe(gulp.dest('dist/js/others'));
console.log('js 文件移动处理完毕!');
// cb(err);
});
// gulp.task('js', ['js-optimize', 'js-move']);
// 执行所有 js 相关任务,并且开启监视
gulp.task('js-watch', ['js'], function() {
console.log('正在监视 js 文件变动');
// 监听 js
var watcher = gulp.watch('src/js/**/*.js', ['js']); // 监视那些文件的变动,以及变动之后执行的任务
watcher.on('change', function(event) {
// 在 CLI 中输出一些提示信息,帮助我们了解程序发生了什么
// console.log('File ' + event.path + ' was ' + event.type + ', running tasks...');
console.log('事件路径: ' + event.path + ' 事件类型: ' + event.type + ', 正在执行的任务:style');
});
});
// 执行所有 js 及 样式 相关任务,并且开启监视
gulp.task('jc', function() {
console.log('正在监视 js 及 样式 文件变动');
// 监听 js
var watcher = gulp.watch('src/@(js|css)/**/*.@(js|scss)', ['js','css']); // 监视那些文件的变动,以及变动之后执行的任务
watcher.on('change', function(event) {
// 在 CLI 中输出一些提示信息,帮助我们了解程序发生了什么
// console.log('File ' + event.path + ' was ' + event.type + ', running tasks...');
console.log('事件路径: ' + event.path + ' 事件类型: ' + event.type + ', 正在执行的任务:js 及 样式');
});
});
// 图片处理
// =======
// 图片压缩
gulp.task('img', function() {
return gulp.src(['src/img/**/*.{png,jpg,gif}'])
.pipe(plumber())
.pipe(cache(imagemin({ // 只压缩修改的图片,没有修改的图片直接从缓存文件读取
progressive: true,
use: [pngquant()] // 使用 pngquant 深度压缩 png 图片
})))
.pipe(gulp.dest('dist/img'));
console.log('图片压缩完毕!');
});
// 合成 sprite 图(只是单一的一个功能,貌似比较难与其他功能串联配合)
gulp.task('sprite', function() {
return gulp.src('src/img/tmp/!(sprite.png|*.css)')
.pipe(spritesmith({
imgName: 'ico.png',
cssName: 'sprite.css'
}))
.pipe(gulp.dest('src/img'));
console.log('sprite 图合成完毕!');
});
// 实时重载 Domain server
// gulp.task('serve', function() {
// browserSync({
// // 注意:请勿同时设置 proxy 和 server,否则会报错
// proxy: "dev01.com.dev",
// // port: 3000,
// // browser: ["google chrome", "firefox"], //默认值为"google chrome"
// reloadOnRestart: false
// });
//
// gulp.watch(['*.html', 'dist/css/**/*.css', 'dist/js/**/*js','dist/images/**/*.*', 'views/**/*.php']).on("change", reload);
// });
// Domain server
gulp.task('serve', function() {
browserSync.init({
proxy: "deva.dev",
port: 3001,
open: "ui",
ui: {port: 3005}
});
});
// gulp.task('serve',function() {
// browserSync({
// server: {
// // host:'localhost:80',
// baseDir: ''
// },
// startPath: 'index.php?homepage&a=login'
// });
//
// gulp.watch(['*.html','css/**/*.css','js/**/*js','images/**/*.*','views/**/*.php'], {cwd: './'}, reload);
// });
// 定义默认任务,执行`gulp`会自动执行(个人认为可以把需要频繁执行的任务放在这里,例如:css、js;而图片压缩之类的就不必了)
// gulp.task('default', function() {
//
// // 监听 sass
// var watcher = gulp.watch('src/css/sass/**/*.scss', ['sass']);
// watcher.on('change', function(event) {
//
// // 在 CLI 中输出一些提示信息,帮助我们了解程序发生了什么
// // console.log('File ' + event.path + ' was ' + event.type + ', running tasks...');
// console.log('事件路径: ' + event.path + ' 事件类型: ' + event.type + ', 正在执行的任务:style');
// });
// });
参考: