上个月底,公司提出了前后端分离的想法,开始研究前后端的一些东西-端分离、前端工程化、模块化。上周我开始准备自己开始。写一个基于Gulp流的前端工程文件,这两天有时间开始着手实现这个想法,但是在写的过程中遇到了一些问题。也正是因为这些问题的解决,让我对Gulp的流处理有了更深的理解,写这篇文章,分享一下这两天在写Gulp的过程中学到的一些东西。准备工作安装Node首先,Gulp是基于Nodejs的,所以安装Nodejs是前提条件。Node可以说是前端神器。有各种基于Node.js的工具。正是因为这些工具让我们可以非常方便的搭建前端项目。更改Node插件的默认安装位置(不是必需的)。我一般不喜欢在C盘放太多和系统无关的东西,通过Node自带的npm安装的插件默认在C盘,但是我把Node安装到D盘最后,如果我要怎么办想让插件安装在Nodejs的主目录下?在Node主目录下创建“node_global”和“node_cache”两个文件夹启动cmd,根据你的目录结构进入如下设置目录更改npmconfigsetprefix"D:\Program\nodejs\node_global"npmconfigsetcache"D:\Program\nodejs\node_cache”自行设置,关闭cmd,打开系统对话框,右击“我的电脑”“属性”-“高级系统设置”-“高级”-“环境变量”。进入环境变量对话框,在系统变量下新建“NODE_PATH”,输入“D:Programnodejsnode_globalnode_module”。由于修改了模块的默认地址,所以必须对上面的用户变量进行相应的修改(将用户变量“PATH”修改为“D:Programnodejsnode_global”),否则在不使用模块时,输入命令会出现“xxx不是内部或外部命令,也不是可运行的程序或批处理文件”错误。经过这四步的设置,安装好的Node插件就可以放到Nodejs的主目录下了。安装Gulp//全局安装Gulpnpminstall-ggulp//在项目中安装Gulpnpminstall--save-devgulp,运行gulp-v。如果没有报错,则安装成功。然后在命令行运行npminit让项目产生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。npminstall--save-devgulp-sass安装后,直接引用gulpfile.js中的配置constsass=require('gulp-sass');//scsscompilegulp.task('scss:dev',()=>{gulp.src('src/scss/*.scss').pipe(sass()).pipe(gulp.dest('dist/css'));//将生成的css文件放入dist/css文件夹下});这里简单介绍一下gulp的两个API:gulp.src()输入匹配提供的匹配模式或匹配模式数组的文件。将返回一个流或可以通过管道传输到其他插件。读取文件gulp.dest()可以通过管道输入,并将写入文件。并重新发出所有数据,因此可以将其传输到多个文件夹,如果该文件夹不存在,它将自动创建。写文件实时刷新的工具有很多,可以实现实时刷新。我自己使用浏览器同步。这个工具非常强大。如果想了解更多它的使用方法,可以查看官网:http://www.browsersync.cn/。首先,我们在项目中安装模块npminstall--save-devbrowser-sync。根据官网上browser-sync和gulp的配置,我们得到如下配置:constbrowserSync=require('browser-sync').create();//实时刷新constreload=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开发流程就出来了好吧,就一个compilescss和一个liverefresh。打包上线所有进程都打包上线。我们更关心静态资源的反缓存和优化。对于css和js的压缩,以及图片的处理,我写的简单流程没有涉及到图片的处理,所以这里只针对css,js,html的处理。我们可以使用gulp-sass来压缩css,因为它在编译scss的时候有一个配置选项可以直接输出压缩后的css。我用gulp-uglify压缩js,用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())//添加散列文件到manifest.pipe(gulp.dest('rev/css'));});//压缩jsgulp.task('js',()=>{gulp.src('src/js/*js').pipe(uglify()).pipe(rev())//将哈希值添加到js.pipe(gulp.dest('dist/js')).pipe(rev.manifest())//添加哈希值文件到list.pipe(gulp.dest('rev/js'));});其中gulp-rev是给css文件名加上hash值,rev.manifest()会生成json文件。这个json文件记录了一个原文件名和加上hash值后的文件名的对应关系。***对应替换html引用时会用到这个对应关系。生成的json文件如下:{"index.css":"index-9dcc24fe2e.css"}由于文件中加入了hash值,所以每次编译出来的css和js都不一样,会导致很多Redundantfiles,这样我们每次生成文件前都可以清空原来的文件。gulp中也有一个插件---gulp-clean可以做到这一点,所以我们可以在编译压缩前清空原文,加上hash值。Emptythegeneratedprojectfileconstclean=require('gulp-clean');//清空文件夹内所有文件//每次打包时清空原文件夹gulp.task('clean',()=>{gulp.src(['dist','rev'],{read:false})//这里设置的dist表示删除dist文件夹及其下的所有文件.pipe(clean());});letadd哈希编码的文件自动添加到html中。前面提到的gulp-rev实现了给文件名添加hash码,但是如何让没有添加hash值的引用在打包完成后自动变为已经添加的hash值参考,一个插件gulp-这里使用了gulp-rev的rev-collector,配置如下://将处理后的css和js引入htmlgulp.task('reCollector',()=>{gulp.src(['rev/**/*.json','src/*.html']).pipe(reCollector({replaceReved:true,//模板中被替换的文件是否可以再次替换,默认为falsedirReplacements:{//标识集合目录替换,因为gulp-rev创建的清单文件不包含任何目录信息,'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中引用的一致,否则替换无法实现。
