基于 Gulp 的浅易前端自动化工程搭建

原文链接:http://mrzhang123.github.io/2016/09/07/gulpUse/
项目链接:https://github.com/MrZhang123/Web_Project_Build/tree/master/gulp

上个月月尾在公司提出关于前后端星散的主意,而且最先研讨关于前后端星散,前端工程化,模块化的一些东西,上周最先我预备自身最先写基于Gulp流的前端工程文件,这两天有时间,动手最先完成这个主意,然则写的历程当中,遇到了一些题目,恰是因为这些题目的处置惩罚让我对Gulp的流式处置惩罚有了更深的明白,写下这篇文章,分享一下这俩天我在写Gulp的时刻学到的一些东西。

预备事情

装置Node

起首Gulp是基于Nodejs的,所以装置Nodejs是条件,Node能够说是前端神器,基于Node有林林总总的东西,恰是因为这些东西让我们异常轻易的构建前端工程。

变动Node插件默许装置位置(非必须)

我自身平常不喜欢在C盘状太多与体系无关的东西,而经由历程Node自带的npm装置的插件默许在C盘,然则我将Node装置到D盘后,想让插件就装置在Nodejs的主目次下,怎样办呢?

  1. 在Node主目次下新建”node_global”及”node_cache”两个文件夹

  2. 启动cmd,输入

    //背面的设置目次依据你的目次构造自行变动
    npm config set prefix "D:\Program\nodejs\node_global"
    npm config set cache "D:\Program\nodejs\node_cache"
  3. 封闭cmd,翻开体系对话框,“我的电脑”右键“属性”-“高等体系设置”-“高等”-“环境变量”。

  4. 进入环境变量对话框,在体系变量下新建”NODE_PATH”,输入”D:Programnodejsnode_globalnode_module”。 因为转变了module的默许地点,所以上面的用户变量都要随着转变一下(用户变量”PATH”修正成”D:Programnodejsnode_global”),要不运用module的时刻会致使输入敕令涌现“xxx不是内部或外部敕令,也不是可运转的递次或批处置惩罚文件”这个毛病。

经由这四步的设置就能够让装置的Node插件放在Nodejs的主目次了。

装置Gulp

//全局装置Gulp
npm install -g gulp
//在项目中装置Gulp
npm install --save-dev gulp

运转gulp -v,假如不报错,示意装置胜利

然后在敕令行运转

npm init

让项目临盆package.json文件

搭建工程

尽人皆知,在开辟工程中有开辟和上线两个历程,在开辟中,我们平常须要自动革新以及及时编译,然则假如上线,我们就须要斟酌许多优化的东西,比方文件编译紧缩,静态资本放缓存处置惩罚等等题目,我自身搭的这个工程只触及到文件编译紧缩,及时革新,静态资本放缓存这三个基础的流程。

在项目的目次构造以下

-------------------project
|   |
|   |--------------dist (该文件夹为打包天生的)
|   |   |
|   |   |----------css
|   |   |   |
|   |   |   |------index-9dcc24fe2e.css
|   |   |
|   |   |----------js
|   |   |   |
|   |   |   |------index-9dcc24fe2e.js
|   |   |----------index.html 
|   |
|   |--------------src
|   |   |
|   |   |----------scss
|   |   |   |------index.scss
|   |   |
|   |   |----------js
|   |   |   |
|   |   |   |------index.js
|   |   |
|   |   |----------index.html
|   |--------------gulpfile.js
|   |--------------package.json

开辟所用流程

文件编译

在工程中预备运用scss作为css的预编译,所以须要应用gulp对scss举行编译,所以起首装置gulp-sass。

npm install --save-dev gulp-sass

装置完成以后,直接在gulpfile.js援用设置

const sass = require('gulp-sass'); //scss编译

gulp.task('scss:dev',()=>{
    gulp.src('src/scss/*.scss')
    .pipe(sass())
    .pipe(gulp.dest('dist/css')); //将天生好的css文件放到dist/css文件夹下
});

这里简朴引见下gulp的两个api:

gulp.src()输入相符所供应的婚配形式或许婚配形式的数组的文件。将返回一个stream或许能够被piped到别的插件中。读文件

gulp.dest()能被pipe进来,而且将会写文件。并从新输出(emits)一切数据,因而能够将它pipe到多个文件夹,假如文件夹不存在则将会自动建立。写文件

及时革新

完成及时革新的东西有许多,我自身运用browser-sync,这个东西的功用异常壮大,想相识它更多的用法能够查看官网:http://www.browsersync.cn/

起首我们在项目中装置该模块

npm install --save-dev browser-sync

依据官网的browser-sync与gulp的设置,获得以下设置:

const browserSync = require('browser-sync').create(); //及时革新
const reload = browserSync.reload;

gulp.task('dev',['scss:dev'],function () {
    browserSync.init({
        server:{
            baseDir:'./'  //设置服务器的根目次
        },
        logLevel: "debug",
        logPrefix:"dev",
        browser:'chrome',
        notify:false //开启寂静形式
    });
    //运用gulp的监听功用,完成编译修正事后的文件
    gulp.watch('src/scss/*.scss',['scss:dev']);
    gulp.watch(('*.html')).on('change',reload);
});

如许,一个简朴的gulp开辟流程就出来了,仅仅只是一个编译scss和一个及时革新。

打包上线一切流程

打包上线,我们更多的是斟酌,静态资本防缓存,优化。对css,js的紧缩,对图片的处置惩罚,我写的这个简朴的流程中并没有触及对图片的处置惩罚,所以这里仅针对css,js,html处置惩罚。

紧缩css我们运用gulp-sass就能够,因为它在编译scss的时刻有一个设置选项能够直接输出被紧缩的css。紧缩js我运用了gulp-uglify,静态资本防缓存运用gulp-rev和gulp-rev-collector。

对css,js的处置惩罚

//scss编译
gulp.task('css',()=> {
    gulp.src('src/scss/*.scss')
        .pipe(sass({
            outputStyle: 'compressed'               //编译并输出紧缩过的文件
        }))
        .pipe(rev())                                //给css增加哈希值
        .pipe(gulp.dest('dist/css'))
        .pipe(rev.manifest())                       //给增加哈希值的文件增加到清单中
        .pipe(gulp.dest('rev/css'));
});
//紧缩js
gulp.task('js', ()=> {
    gulp.src('src/js/*js')
        .pipe(uglify())
        .pipe(rev())                                //给js增加哈希值
        .pipe(gulp.dest('dist/js'))
        .pipe(rev.manifest())                       //给增加哈希值的文件增加到清单中
        .pipe(gulp.dest('rev/js'));
});

个中gulp-rev是为css文件名增加哈希值,而rev.manifest()会天生一个json文件,这个json文件中记录了原文件名和增加哈希值后的文件名的一个对应关联,这个对应关联在末了对应替代html的援用的时刻会用到。

天生的json文件以下:

{
  "index.css": "index-9dcc24fe2e.css"
}

因为给文件增加了哈希值,所以每次编译出来的css和js都是不一样的,这会致使有许多冗余文件,所以我们能够每次在天生文件之前,先将本来的文件悉数清空。

gulp中也有做这个事情的插件—gulp-clean,因而我们能够在编译紧缩增加哈希值之前先将原文将清空。

清空天生的项目文件

const clean = require('gulp-clean');                 //清空文件夹里一切的文件
//每次打包时先清空原有的文件夹
gulp.task('clean', ()=> {
    gulp.src(['dist', 'rev'], {read: false}) //这里设置的dist示意删除dist文件夹及其下一切文件
        .pipe(clean());
});

让增加哈希编码的文件自动增加到html中

前面提到的gulp-rev完成了给文件名增加哈希编码,然则在打包完成后怎样让本来未增加哈希值的援用自动变成已增加哈希值的援用,这里用到gulp-rev的一个插件gulp-rev-collector,设置以下:

//将处置惩罚过的css,js引入html
gulp.task('reCollector',()=>{
    gulp.src(['rev/**/*.json','src/*.html'])
        .pipe(reCollector({
            replaceReved: true,  //模板中已被替代的文件是不是还能再被替代,默许是false
            dirReplacements: {   //标识目次替代的鸠合, 因为gulp-rev建立的manifest文件不包括任何目次信息,
                'css/': '/dist/css/',
                'js/': '/dist/js/'
            }
        }))
        .pipe(gulp.dest('dist'))
});
并没有一般替代?

在我自身写的时刻,涌现这个题目,运转完成该使命后,html中的css和js援用并没有发生变化,网上搜了半天,才晓得是因为自身用了gulp-rename插件,然后将文件名都增加了.min(至于为何增加,仅仅是因为是紧缩过的,应当写个)而在自身写的html内里援用的文件并没有.min,因为gulp-rev-collector在替代的时刻依据天生的json文件替代,在json中,文件都有了.min而在html中没有,所以没法婚配,天然也就不能完成替代了,所以在替代的时刻肯定要注意gulp-rev天生的json文件中的css,js与html中的援用的一样,不然没法完成替代。

<font color=”red”>在gulp-rev-collector的api中有一个revSuffix,这个看起来能够完成类似于gulp-rename的功用,然则不晓得该怎样用,人人假如晓得的话请通知我…</font>

实行一切使命

完成上面几个步骤后我们将一切使命串起来,让其能够一条敕令然后悉数实行

gulp.task('build',['clean', 'css', 'js', 'reCollector']);

再次明白gulp

gulp—它的task是递次实行吗?

本认为到这里,就算是写完了,运转,圆满,打包天生文件,再运转一次,报错了!!!!

[19:04:57] Finished 'default' after 7.38 μs
stream.js:74
      throw er; // Unhandled stream error in pipe.
      ^

Error: ENOENT: no such file or directory, stat 'D:\project\dist\js\index-6045b384e6.min.js'
    at Error (native)

提醒我找不到这个文件,这让我很忧郁啊,然后我离开实行,很ok,能够确定是实行递次有题目,很可能在没有清算完造诣实行背面了,查了gulp的官网文档才晓得自身gulp的pipe是一个一个使命举行的,是同步的,然则每一个task之间是不同步的,是一同举行的,这也考证了我的猜测,所以在网上找怎样处置惩罚这个题目,找到一个叫run-sequence的npm插件,设置文件以下:

//举行打包上线
gulp.task('build', ()=> {
    runSequence('clean', ['css', 'js'], 'reCollector');
});

本认为运转就ok,效果,照样报错,这里就触及到对gulp的另一个明白

run-sequence插件对异步使命的处置惩罚

在用这个插件让使命有序举行后,我想进一步直观的看到它对使命的序列化,自身写了一个demo,以下:

gulp.task('a',function(){
    setTimeout(function () {
        console.log(1);
    },30);
});
gulp.task('b',function() {
    console.log(2);
});
gulp.task('ab',function(){
    runSequence('a','b');
});

然则这里就涌现题目了,runSequence不论用了,找插件的申明和gulp官方文档,本来异步使命,像setTimeout,readFile等,须要增加一个callback的实行,这里的callback()就会返回一个promise的resolve(),通知背面的使命,当前使命已完成,背面能够继承实行了,所以在task a内里实行callback。

gulp.task('a',function(cb){
    setTimeout(function () {
        console.log(1);
        cb();
    },30);
});

那为何前面写的那些使命不须要增加一个callback呢?因为gulp的pipe流让每一个task中的小使命(每一个pipe)递次实行,从而全部pipe流是同步的,并非异步使命,所以并不须要手动让其返回promise,run-sequence会自动帮我们治理。

总结

至此,我们就完成了一个浅易的基于gulp的前端工程的搭建,许多东西确切,想着并不难,做起来会涌现林林总总意想不到的题目,gulp很早就晓得,都是单个使命在写,然后用哪一个实行哪一个敕令,直到自身写完这个这个简朴的工程,才对gulp有了更深切的明白。

    原文作者:枫s的思念
    原文地址: https://segmentfault.com/a/1190000006846606
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞