gulp+webpack+node-sever+http-proxy
大前端项目
相信很多同学在前后端分离的开发中一定遇到过各种各样的棘手问题,
1:资源缓存,浏览器缓存各种资源使得最新的css或js或img或icon无法及时展示出来,需要清理浏览器缓存,在混合开发中甚至需要清理app数据才能解决,今天我为你解决;
2:模块化,对于常用的js和css使用模块化工具require.js进行打包便于项目管理和提高代码复用性,减少不必要的代码等,好处多多;
3:解析各种语法,ES6,LESS,SASS等啥的,以及语法检测,代码质量啥的
4:多环境打包,一个项目一般包括开发,测试,预生产,自动切换请求地址地址,
5:js压缩,css压缩,图片压缩,更换资源版本号,打zip包啥的;
6:代理后台接口,把后台接口代理到本地,解决后台接口跨域问题;
直接上代码
项目目录
配置文件直接上代码吧,注释很清楚,我就不解释了
gulp+webpack
const gulp = require('gulp');
const plugins = require('gulp-load-plugins')();
const through2 = require('through2');
const minimist = require('minimist');
const pngquant = require('imagemin-pngquant');
const gutil = require('gulp-util');
//路径对象, 方便统一管理
var jPath = {
page:'./page/',
pageJsDir:'./page/js',
pageHtml:'./page/html/*.html',
pageJs:'./page/js/*.js',
pageCss:'./page/css/*.css',
pageImg:'./page/img/*.*',
bund:'./bund/',
bundHtml:'./bund/html/',
bundJs:'./bund/js/',
bundCss:'./bund/css/',
bundImg:'./bund/img/',
revPath:'./rev/**/*.json',
revCss:'./rev/css_rev',
revJs:'./rev/js_rev',
node_modules_js:'./node_modules/**/*.js',
node_modules_css:'./node_modules/**/*.css'
}
//根据路径获取项目路径
var projectPath = '../gulpTest1/';
//根据路径获取项目名
varprojectName = projectPath.split('../')[1];
//根据路径获取存放编译文件的目录名
vardistName = jPath.bund.split('/');
distName = distName[distName.length - 1];
var config = {};
gulp.task('dev',function(){
plugins.runSequence(
'constants',
['destHtml','devMiniCSS','devMiniJS'],
'entry',
'watch'
)
});
//测试
gulp.task('test',function(){
plugins.runSequence(
'constants',
['update','minImg']
)
});
//预生产正式
gulp.task('build',function(){
plugins.runSequence(
'constants',
['update','minImg']
)
});
gulp.task('default',function(){
plugins.runSequence(
'constants',
['miniJS','miniCSS']
)
});
// 监视文件变化,自动执行任务
gulp.task('watch', function(){
gulp.watch(jPath.pageJs,['devMiniJS']);
gulp.watch(jPath.pageCss, ['devMiniCSS']);
gulp.watch(jPath.pageHtml,['destHtml']);
gulp.watch(jPath.pageImg,['minImg']);
})
/*
* 多环境配置,
* 默认dev环境
*/
var knowOptions = {
string: 'env',
default: {
env: process.env.NODE_ENV 'dev'
}
};
var options = minimist(process.argv.slice(2), knowOptions);
//生成filename文件,存入string内容
function string_src(filename, string) {
var src = require('stream').Readable({ objectMode: true })
src._read = function () {
this.push(new gutil.File({ cwd: "", base: "", path: filename, contents: new Buffer(string) }))
this.push(null)
}
return src
}
//生成环境地址.js文件
gulp.task('constants', function() {
//读入config.json文件
var myPath = require('./respPath.json');
//取出对应的配置信息
//命令行传回来的参数
var envConfig = myPath[options.env];
var conConfig = 'module.exports = ' + JSON.stringify(envConfig);
//生成config.js文件
return string_src("./respPath.js", conConfig)
.pipe(gulp.dest(projectPath+'api'))
});
//生成环境地址.js文件
gulp.task('entry', function() {
return string_src("./respPath.json", config)
.pipe(gulp.dest(projectPath+'api'))
});
//webpack打包
gulp.task('devMiniJS',function(){
gulp.src(jPath.pageJs,)
.on('data',function(file){
handle(file);
})
.on('end',function(file){
gulp.src(jPath.pageJs,)
.pipe(plugins.webpack({
debug: true,
entry:config,
output:{
filename:"[name].js"
},
stats:{
colors:true
}
}))
.pipe(plugins.babel({
presets: ['es2015']
}))
//输出文件
.pipe(gulp.dest(jPath.bundJs))
})
})
//输出html
gulp.task('destHtml',function(){
return gulp.src(jPath.pageHtml,)
.pipe(gulp.dest(jPath.bundHtml))//输出压缩后的HTML
});
gulp.task('devMiniCSS',function(){
return gulp.src(jPath.pageCss,)
.pipe(gulp.dest(jPath.bundCss))
});
gulp.task('miniJS',function(){
return gulp.src(jPath.pageJs,)
.on('data',function(file){
handle(file);
})
.on('end',function(file){
gulp.src(jPath.pageJs,)
.pipe(plugins.webpack({
debug: true,
entry:config,
output:{
filename:"[name].js"
},
stats:{
colors:true
}
}))
.pipe(plugins.babel({
presets: ['es2015']
}))
//压缩js文件
.pipe(plugins.uglify())
//输出文件
.pipe(gulp.dest(jPath.bundJs))
//生成md5
.pipe(plugins.rev())
//生成md5的json文件
.pipe(plugins.rev.manifest())
//替换
.pipe(replaceSuffix())
//输出该文件
.pipe(gulp.dest(jPath.revJs))
})
});
gulp.task('miniCSS',function(){
return gulp.src(jPath.pageCss)
//压缩
.pipe(plugins.minifyCss())
//输出
.pipe(gulp.dest(jPath.bundCss))
//生成md5
.pipe(plugins.rev())
//生成md5的json文件
.pipe(plugins.rev.manifest())
.pipe(replaceSuffix())
//输出该文件
.pipe(gulp.dest(jPath.revCss))
});
//图片压缩
gulp.task('minImg',function(){
return gulp.src(jPath.pageImg)
.pipe(plugins.imagemin({
progressive: true,
svgoPlugins: [],
use: [pngquant()]
}))
.pipe(gulp.dest(jPath.bundImg));
});
//输出文件名更换
gulp.task("update",['miniCSS','miniJS'],function (cb) {
gulp.src([jPath.revPath,jPath.pageHtml])
//利用revCollector的可配置,去满足我们需要的模式;
.pipe(plugins.revCollector({
revSuffix: '\\?v=[0-9a-f]-?'
}))
.pipe(gulp.dest(jPath.bundHtml))
});
/*
* 更换版本号
* replaceSuffix把替content-bf1194aded.css换成content.css?v=bf1194aded
*/
function replaceSuffix() {
//匹配出-7ef5d9ee29.css,用于后面做文章
var pattern =/-[0-9a-f]-?\.[^"]*/gmi;
return through2.obj(function(file, encoding, done) {
var content =String(file.contents).replace(pattern,function(match,pos,origin){
//匹配出7ef5d9ee29,用于后面拼接
var pat=/[0-9a-f]-?/g;
if(pat.test(match)){
//如果$'和$&这句话看不懂,红宝书第五章正则表达式部分该复习了;
return RegExp["$'"].concat("?v=", RegExp["$&"]);
}else{
return match;
}
});
file.contents = new Buffer(content);
this.push(file);
done();
});
}
//获取各项流数据
function handle(file) {
//获取路径
try {
var srcPath = file.path file.history[0];
} catch (e) {
console.log('获取路径失败');
return;
}
if (!srcPath) return;
//获取 : 文件类型 (jscsshtml...), 文件名 , 编译后的存放路径
var taskType = tools.getType(srcPath),
fileName = tools.getName(srcPath),
distPath = tools.getDistPath(srcPath, fileName);
//webpack的entry参数
config[fileName.split('.')[0]] = jPath.pageJsDir+'/'+file.relative;
}
var tools = {
//根据路径获取文件类型
getType: function(path) {
var typeTemp = path.split('.');
return typeTemp[typeTemp.length - 1];
},
//根据路径获取文件名
getName: function(path) {
var nameTemp = path.split('\\');
return nameTemp[nameTemp.length - 1];
},
//根据路径&文件名获取编译后文件的存放路径
getDistPath: function(path, name) {
//匹配一个反斜杠需要在字符串里写4个反斜杠
return path.replace(
//替换scr为存放编译文件的目录名
new RegExp(projectName + '\\\\src', 'g'),
projectName + '\\' + distName
).replace(
//删除路径中的文件名
new RegExp(name, 'g'),''
);
}
};
http.js
var PORT = 3000;
var http = require('http');
var url = require('url');
var fs = require('fs');
var mine = require('./mime').types;
var path = require('path');
var httpProxy = require('http-proxy');
var proxy = httpProxy.createProxyServer({
target: 'https://loan.moneytocar.com/yuedianqian-wap', //接口地址
// 下面的设置用于https
ssl: {
key: fs.readFileSync('server_decrypt.key', 'utf8'),
cert: fs.readFileSync('server.crt', 'utf8')
},
secure: false
});
proxy.on('error', function(err, req, res) {
res.writeHead(500, {
'content-type': 'text/plain'
});
console.log(err);
res.end('Something went wrong. And we are reporting a custom error message.');
});
var server = http.createServer(function(request, response) {
var pathname = url.parse(request.url).pathname;
//var realPath = path.join("main-pages", pathname); // 指定根目录
var realPath = path.join("./", pathname);
console.log('此处是pathname' + pathname);
console.log(realPath);
var ext = path.extname(realPath);
ext = ext ? ext.slice(1) : 'unknown';
//判断如果是接口访问,则通过proxy转发
if(pathname.indexOf("zs/") > 0) {
console.log('请求被转发了');
proxy.web(request, response);
return;
}
fs.exists(realPath, function(exists) {
if(!exists) {
response.writeHead(404, {
'Content-Type': 'text/plain'
});
response.write("This request URL " + pathname + " was not found on this server.");
response.end();
} else {
fs.readFile(realPath, "binary", function(err, file) {
if(err) {
response.writeHead(500, {
'Content-Type': 'text/plain'
});
response.end(err);
} else {
var contentType = mine[ext] "text/plain";
response.writeHead(200, {
'Content-Type': contentType
});
response.write(file, "binary");
response.end();
}
});
}
});
});
server.listen(PORT);
console.log("Server runing at port: " + PORT + ".");
mime.js
exports.types = {
"css": "text/css",
"gif": "image/gif",
"html": "text/html",
"ico": "image/x-icon",
"jpeg": "image/jpeg",
"jpg": "image/jpeg",
"js": "text/javascript",
"json": "application/json",
"pdf": "application/pdf",
"png": "image/png",
"svg": "image/svg+xml",
"swf": "application/x-shockwave-flash",
"tiff": "image/tiff",
"txt": "text/plain",
"wav": "audio/x-wav",
"wma": "audio/x-ms-wma",
"wmv": "video/x-ms-wmv",
"xml": "text/xml",
"woff": "application/x-woff",
"woff2": "application/x-woff2",
"tff": "application/x-font-truetype",
"otf": "application/x-font-opentype",
"eot": "application/vnd.ms-fontobject"
};
由于项目中大量代码是网上找不到的,或者不全的,所以各位如果转载请注明出处,谢谢
领取专属 10元无门槛券
私享最新 技术干货