gulp初体验

168 篇文章 6 订阅
159 篇文章 3 订阅

前段时间我们搞了个研究和测试性质的cesium项目,基本都是前端的东西。也就是说,主要就是一些js。于是想到用gulp将项目进行发布。据说当今最热门的发布工具是webpack,其次是gulp。但webpack适合SPA,单页应用,而gulp适合传统的多页系统。我们项目非SPA,因此选用gulp。

gulp,就是一个项目发布工具,作用我看无非主要就是压缩js\css\html,然后还可以给文件加上版本号。压缩可以起到减少文件尺寸,节约带宽,加快加载,同时有一定保密作用;而加上版本号,则可以使浏览器缓存失效,避免程序已更新,但客户还是看到老效果这种弊端。这个对CDN就非常有用。但是这个功能估计要跟发布时的监控机制(?)结合起来才有意义,如果没有更新的代码,版本号也都跟之前不一样,迫使客户端全部重新加载一遍,反而造成浪费。我还估计,这些发布工具都跟自动部署这些概念有关,但我没有试过,可见多落后。这也是我这次花了一点时间来用一下gulp的原因。

闲话休提,以下是一些笔记:

一、准备环境

0、安装npm

1、安装gulp

npm install --save-dev gulp 

也可以缩写成

npm i -D gulp

i就是install,-D 就是 --save-dev。至于–save-dev有什么作用,我搞不大清楚

2、安装各种插件
这些插件在发布时需要用到。

npm i -D gulp-rev gulp-rev-replace gulp-useref gulp-filter gulp-uglify-es gulp-csso gulp-minify-html gulp-clean

3、如果受到蛊惑,使用了淘宝的镜像

,可能会出现类似“ERR!Unexpected end of JSON input while parsing near”这样的错误
则应:

1)删掉package.lock.json

2)清除cache

npm cache clean --force

3)不再使用淘宝镜像

npm set registry https://registry.npmjs.org/	

二、编写发布脚本

这个脚本一般叫gulpfile.js。看资料,说可以有多个这样的文件,分别完成不同的任务。我因为不大熟悉,就全部写在一个文件里了。内容其实也是js。用js来发布js。

我这份发布脚本,流程主要是

1)将发布目录清空

2)拷贝一些无须特别处理的文件,如图片,json;还有一些第三方js,它们本身就已经处理过了,直接拷贝就行了。

3)处理css,css文件加上版本号
在这里插入图片描述

4)处理js
js我没有加版本号。因为有许多js文件是动态加载的,加了版本号会404。也有一些插件,如gulp-rev-suffix,好像还是一个中国人写的,可以将版本号弄成

<script src="script/script-version.js?rev=17a5da6c8a2d875cf48aefb722eefa07"></script>

这种形式。但前提是html里要预留特殊标记:

<script src="script/script-version.js?rev=@@version"></script>

我觉得这很扯。

5)处理html

以下是 gulpfile.js 的完整示例:

/*
	gulpfile.js
*/
const { series,parallel,src,dest } = require('gulp');

const rev = require('gulp-rev'),//添加版本号
	revReplace = require('gulp-rev-replace'),//更新index.html下的引用
	useref = require('gulp-useref'),//合并css或js文件
	filter = require('gulp-filter'),//筛选和恢复
	uglify = require('gulp-uglify-es').default,//压缩JS文件
	csso = require('gulp-csso'),//压缩CSS文件
	minifyHtml = require('gulp-minify-html'),//压缩html
	clean = require('gulp-clean');//清理文件或文件夹	

//public函数,那么我们发布的时候的命令就是 gulp build	
exports.build = series(
	empty,
	copy1,copy2,
	parallel(css,js),
	html
);

const dist = "./dist";
const MANIFEST = dist + "/rev-manifest.json";

function empty(){//打包前先清掉目标发布文件夹
	return src('dist/',{read: false,allowEmpty:true})
		.pipe(clean());	
}
function copy1(){//copy 文件夹libs to dist
	return src(['code/libs/**'], {restore: true})
		.pipe(dest(dist + '/libs'));
}
function copy2(){//直接复制无须处理的文件,如图片,json等等
	return src(['code/**/*','!code/**/*.js','!code/**/*.css','!code/**/*.html','!code/libs/**','!code/.svn/**'], {restore: true})
		.pipe(dest(dist));
}
function html(){
	let manifest = src("./dist/rev-manifest.json");
	//let indexHtmlFilter = filter(['**/*.html', '!**/widget.html'], {restore: true});	
	return src(['code/**/*.html','!code/libs/**','!code/.svn/**'], { sourcemaps: true })
		.pipe(minifyHtml({
			empty:true,spare:true,quotes:true
		}))
		//.pipe(indexHtmlFilter)/*筛选html文件*/
		//.pipe(rev())/*生成哈希版本号*/
		//.pipe(indexHtmlFilter.restore)/*放回流里*/
		.pipe(revReplace({manifest: manifest}))/*更新index引用*/
		.pipe(dest(dist));/*文件流放到dist目录下*/
}
function css(){
	return src(['code/**/*.css','!code/libs/**','!code/.svn/**'], { sourcemaps: true })
		.pipe(useref())/*处理注释压缩*/
		.pipe(csso())/*压缩css文件*/
		.pipe(rev())/*生成哈希版本号*/
        .pipe(dest(dist))
        .pipe(rev.manifest(MANIFEST,{base:dist,merge: true}))
		.pipe(dest(dist));/*文件流放到dist目录下*/	
}
function js(){
	//var jsFilter = filter(['**/*.js','!code/js/lan3d.js'], {restore: true});	
	return src(['code/**/*.js','!code/libs/**','!code/.svn/**'], { sourcemaps: true })
		.pipe(useref())/*处理注释压缩*/
		.pipe(uglify())/*压缩js文件*/
		//.pipe(jsFilter)/*筛选js文件*/	
		//.pipe(rev())/*生成哈希版本号*/
        //.pipe(dest('dist'))
        //.pipe(rev.manifest(MANIFEST,{merge: true}))
		//.pipe(jsFilter.restore)/*放回流里*/
		.pipe(dest(dist));/*文件流放到dist目录下*/	
}

运行结果
在这里插入图片描述

三、要点

1、exports
一般网上的资料说的是gulp.task(),但看gulp官方网站,已经不推荐这种方式了。而是采用 exports.*** 的方式

2、gulp对es6或以上的支持
比如 const,Promise,async await之类的语法,关键是要:


gulp-uglify-es这个插件来进行JS压缩,而不是一般资料里说的 gulp-uglify。

千万不要照网上说的什么采用babel或@babel,永远都是报错。害死人!!!

否则的话,你就在无尽的 Caused by: SyntaxError: Unexpected token: name ?_regeneratorRuntime?, expected:punc ?;? 之类的报错中死循环。


**3、一些用法**

```js
function html(){
	let manifest = src("./dist/rev-manifest.json");
	let indexHtmlFilter = filter(['**/*.html', '!**/widget.html'], {restore: true});	
	return src(['code/**/*.html','!code/libs/**','!code/.svn/**'], { sourcemaps: true })
		.pipe(minifyHtml({
			empty:true,spare:true,quotes:true
		}))
		.pipe(indexHtmlFilter)/*筛选html文件*/ //<------------------------
		.pipe(rev())/*生成哈希版本号*///
		.pipe(indexHtmlFilter.restore)/*放回流里*///<------------------------
		.pipe(revReplace({manifest: manifest}))/*更新index引用*/
		.pipe(dest(dist));/*文件流放到dist目录下*/
}

筛选,处理,然后放回流里。本来src这里已经指定了待处理的文件类型(html),然后处理过程中,加入这个筛选,是更精细的范围。处理完之后,放回流里,那么这个筛选结束了。筛选,在这里相当于大范围中的小范围,不同对象作不同的处理。

4、发布之后,一些不那么规范的代码可能会报错。这也算是一种质量控制机制吧。

附录
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值