gulp尝试开发

Author Avatar
carvenzhang 3月 10, 2016
  • 在其它设备中阅读本文章

背景

这是挺久之前的事情了,还是觉得先记录下来,免得自己忘记了。
在实习的公司做web开发,gulp 是经常用到的,可是我做的不仅仅的前端,还包括后台,
所以将前端文件移至后台这种事当然也需要我做啦,用gulp,但是,文件移至后台目录后,资源文件的路径必须修改,
(我做的后台的是用express做的),一时间,没有找到适合的插件,于是我萌生了自己开发一下gulp插件的想法。

开发流程

参考了几篇博客
Gulp插件制作指南
Gulp:插件编写入门

先来看一下插件的全部代码

'use strict';
var gutil = require('gulp-util');
var through = require('through2');
const PLUGIN_NAME = 'gulp-url-replace';
module.exports = function (options) {
    var pattern = [];
    var testClose = /\/$/;
    var pp;
    for (pp in options) {
        var odir = {};
        if (testClose.test(pp)) {
            odir.o = new RegExp(pp, 'g');
        }
        else {
            odir.o = new RegExp(pp + '/', 'g');
        }

        if (testClose.test(options[pp])) {
            odir.n = options[pp];
        }
        else {
            odir.n = options[pp] + '/';
        }
        pattern.push(odir);
    }

    return through.obj(function (file, enc, cb) { //流/编码/回调

        if (typeof options !== 'object') {
            this.emit('error', new gutil.PluginError(PLUGIN_NAME, 'Streaming not supported'));
            return cb();
        }

        if (file.isNull()) {
            this.push(file);
            return cb();
        }

        if (file.isStream()) {
            this.emit('error', new gutil.PluginError(PLUGIN_NAME, 'Streaming not supported'));
            return cb();
        }

        var content = file.contents.toString();
        pattern.forEach(function (r) {
            content = content.replace(r.o, r.n);
        });
        file.contents = new Buffer(content);


        this.push(file);
        cb();
    });
};

省略出主干就是

//引入依赖
var gutil = require('gulp-util');
var through = require('through2');
//暴露主函数
module.exports = function (options) {
    //返回处理流 Node Stream
    return through.obj(function (file, enc, cb) {
        // 主体处理
    });
};

下面分步解释:

引入依赖模块

ar gutil = require('gulp-util');
var through = require('through2');

gulp-util: 错误日志打印模块,按照gulp的统一规范打印错误日志
through2: Node Stream的简单封装,目的是让链式流操作更加简单

gulp 的 through2 开发标准样例

const PLUGIN_NAME = 'gulp-url-replace';
module.exports = function (options) {
    return through.obj(function (file, enc, cb) {

        // 如果文件为空,不做任何操作,转入下一个操作,即下一个 .pipe()
        if (file.isNull()) {
            this.push(file);
            return cb();
        }

        // 插件不支持对 Stream 对直接操作,跑出异常
        if (file.isStream()) {
            this.emit('error', new gutil.PluginError(PLUGIN_NAME, 'Streaming not supported'));
            return cb();
        }

        // 将文件内容转成字符串
        var content = file.contents.toString();

        //对文件内容处理
        content = dosomething(content);

        // 然后将处理后的字符串,再转成Buffer形式
        file.contents = new Buffer(content);

        // 下面这两句基本是标配啦,可以参考下 through2 的API
        this.push(file);

        cb();
    });
};

以上两步就是开发gulp插件的步骤了

gulp-url-replace 核心逻辑

//正则保存的数组
var pattern = [];
//测试 源路径是否以“/”结尾
    var testClose = /\/$/;
    var pp;
    // odir参数正则话,并统一以“/”结尾
    for (pp in options) {
        var odir = {};
        if (testClose.test(pp)) {
            odir.o = new RegExp(pp, 'g');
        }
        else {
            odir.o = new RegExp(pp + '/', 'g');
        }

        if (testClose.test(options[pp])) {
            odir.n = options[pp];
        }
        else {
            odir.n = options[pp] + '/';
        }
        pattern.push(odir);
    }

    //省略

    //转化成字符串
    var content = file.contents.toString();
    //循环正则替换
    pattern.forEach(function (r) {
        content = content.replace(r.o, r.n);
    });
    //转化回node stream
    file.contents = new Buffer(content);

    //省略

如此,就完成了html中资源路径的替换

注意点

gulp的流处理是逐个处理的
例如

gulp.src('./1.txt,./2.txt')
.pipe(replace())
...

那么 replace() 就会执行两次,两次传入的 file 分别是 1.txt和2.txt,
而不是两个文件一起传进来

使用

npm install gulp-url-replace --save-dev
var gulp = require('gulp');
var replace = require('gulp-url-replace')
gulp.task('move', function(){
    gulp.src('./*.html')
    .pipe(replace({
                      'lib/': '<%= stHost %>/node/public/lib/',
                      'img/':'<%= stHost %>/node/public/img/',
                      'css/': '<%= stHost %>/node/public/css/',
                      'js/': '<%= stHost %>/node/public/js/',
                  }))
    .pipe(gulp.dest("../production/views/"))
})

总结

虽然写法,publish,测试方面都不规范,但是,也是学到了gulp开发的一点知识,
以后可以自己本地做些可能用到的gulp插件
目前源代码已经发布在 github上
gulp-url-replace