基于 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分钟 一次以保证尽量与官方服务同步)。

淘宝镜像使用方法;

  1. 安装 cnpm 插件:npm install -g cnpm --registry=https://registry.npm.taobao.org

然后就可以用 cnpm命令从淘宝镜像获取插件包了;当然,你这时候依旧可以用npm命令从官方服务获取插件包。

cnpm支持除 publish 之外的原生 npm 所有命令。

(二)配置 gulp 自身

请先安装 nodejs(自带 npm)环境。

下面开始进行基于 gulp 的自动化构建方案的配置:

  1. 在 CLI 中切换到项目目录(例如:cd d:/wamp/www/),执行命令:npm init(中间会需要你填写一些信息,如果嫌烦的话,可以全部回车确认过掉),最后将生成一个 package.json 文件(依赖模块json文件,在项目目录下执行 npm install 会安装项目所有的依赖模块,方便++自动化构建方案在项目之间的的快速复用++)。

  2. Install gulp globally.

全局安装 gulp (如果之前进行过 gulp 全局安装,请运行npm rm --global gulp以确保旧版本的 gulp 不与 gulp-cli 相冲突)

$ npm install --global gulp-cli
  1. Install gulp in your project devDependencies

项目的开发依赖中安装 gulp

$ npm install --save-dev gulp
  1. 项目根目录创建一个 gulpfile.js 文件
var gulp = require('gulp');

gulp.task('default', function() {
  // place code for your default task here
});
  1. 至此,gulp 本身已经配置好了。可以尝试运行以下命令:
$ gulp

这将运行默认任务,但目前默认任务是空的,所以实际效果是什么也不干。

如果要运行某个具体的任务(task), 请使用 gulp <task> <othertask>


  1. 现在你拥有一个空的 gulpfile.js 并且所有东西都已经安装。那么怎样才能真正地开始呢

请查看 recipes(方法、秘诀、食谱)一系列文章 获取更多信息。

  1. 如何使用 API:API 文档
  2. 插件: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 工具将直接显示原始的开发代码,而不是转换后的代码。

  • npm 插件文档

  • 安装:文档没写...那就按照惯例作为项目的开发依赖来安装吧~

  • 用法:

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');
//     });
// });

参考:

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,294评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,493评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,790评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,595评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,718评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,906评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,053评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,797评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,250评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,570评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,711评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,388评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,018评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,796评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,023评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,461评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,595评论 2 350

推荐阅读更多精彩内容