gulp+webpack+angular1的一点小经验(第一部分gulp与webpack的整合)
时间匆匆如流水继上周熟悉了gulp的初步安装与环境配置以后,我的项目又进入了新的阶段!
这篇文章将把我这一周遇到的一些问题,以及解决的方式做一个小小的总结,不一定记的完整,但都是个人的一点经验,分享给大家。有什么错误疏漏还望指正。
1.angular还是vue?
这里我是有很大的犹豫的,最后的结果是angular。这里有很多私心,这个项目需要技术上的认同,angular作为一个热门前端框架拥有更大的知名度,这是我选择angular的一部分原因。另外如果详细的对比,团队技术如果从jquery转型,可以尝试接触vue,vue的上手更简单,这里不做展开了。
2.requirejs还是webpack?
最后的决定是用webpack,因为我requirejs要到浏览器端去进行代码的组织,而webpack在上线之前就把这些做好了,所以性能应该更好。而且webpack可以打包其他类型资源,如css与图片,虽然我现在不打算用这些功能,但能给我留下一些扩展改变的空间。最后requirejs和angular的组合需要引入angular的异步插件,这样让我望而却步。而webpack引入angular只需要一句require('angular');
当然,这里边也有些坑,不过都是后话了。
3.那么现在开始整合吧,先从webpack与gulp的整合开始。
webpack与gulp的整合(当然前提是安装了webpack,同学们自己去官网查看安装喽),可以通过gulp的一个插件来做,这个插件的名字叫gulp-webpack,名字是不是相当直观?最简单的使用方式如下:
gulp-webpack的npm文档
gulpWebpack = require('gulp-webpack');
...//stream
.pipe(gulpWebpack(require('./webpack.config.js')))
...//stream
遇到的坑一个(采用配置文件运行webpack失败),这个链接里有详细的问答: gulp-webpack的坑
好了,这两个就配置好了,那么项目整合angular之前,我们还有一件事没有做,那就是watch
对了,watch很重要啊,实时的编译写好的代码,这样才能更有效率的搭建框架,编写代码。
watch的同时,我们还想要把自动缓存清理的机制加进去。从网上查了,gulp的插件rev配合revCollector可以完成这个任务。这里有一篇很不错的文章
gulp解决项目部署缓存
读完之后,我们了解到,这样做对于我的服务器,还不是很完美,因为我没有静态资源服务器啊,而且上面的资源当然也不是永不过期。相反的,如果资源没用我就希望尽快的删掉。从网上看了一些,感觉没有合适我的,于是就需要自己动手删掉。比如编译sass,直接使用rev的流程是这样的:
.pipe(sass.sync().on('error', sass.logError))
.pipe(minifyCss())
.pipe(rename(function(path){
path.basename=path.basename;
path.extname = ".css";
}))
.pipe(rev({merge: true}))
.pipe(gulp.dest(distCss))
.pipe(rev.manifest())
.pipe(gulp.dest(distRev+'/css'));
那么在进入rev步骤之前,我们要把服务器上已有的文件删掉,删文件就用del这个命令,需要一个参数,要删掉的文件的路径,我们用这个through2这个命令来获取gulp流中的文件路径,地址稍微手动修改一下,指到编译结果的文件夹里:
var gulp = require('gulp'),
sass = require('gulp-sass'),
rename = require('gulp-rename'),
minifyCss = require('gulp-minify-css'),
debug = require('gulp-debug'),
rev = require("gulp-rev"),
revCollector = require("gulp-rev-collector"),
through = require("through2"),
del = require("del");
gulp.task('compile-sass',function(){
return gulp.src('src/scss/*.scss')
.pipe(changed(distCss,{extension:'.css'}))
.pipe(debug({title:'debuging:'}))
.pipe(through.obj(function(chunk,encode,callback){
var delPath = chunk.cwd+"/"+distCss+"/"+chunk.relative.substring(0,chunk.relative.lastIndexOf("."))+"-*"+".css";
console.log(delPath);
del(delPath);
this.push(chunk);
callback();
}))
.pipe(sass.sync().on('error', sass.logError))
.pipe(minifyCss())
.pipe(rename(function(path){
path.basename=path.basename;
path.extname = ".css";
}))
.pipe(rev({merge: true}))
.pipe(gulp.dest(distCss))
.pipe(rev.manifest())
.pipe(gulp.dest(distRev+'/css'));
});
gulp.task('revCollectorHtml',function(){
return gulp.src(['webContent/rev/**/*.json','webContent/index.html'])//注意参数是一个数组,用【】包起来的,要不然会报无法给第二个参数创建cwd属性的错误
.pipe(revCollector({
replaceReved:true //一定要加上这一句,不然不会替换掉上一次的值
}))
.pipe(gulp.dest(distBase));
});
这样,watch的任务就变成了:监听文件变化,并在变化以后,将rev-collector任务完成。我们采用异步的策略来做这件事:
var watchScss = gulp.watch('src/scss/*.*',gulpSync.sync([['compile-sass'],'revCollectorHtml']));
我的文件目录结构如下:
│ gulpfile.js
│ karma.conf.js
│ package.json
│ webpack.config.js
│
├─node_modules
├─src
│ │ index.html
│ │
│ ├─js
│ │ │ app.js
│ │ │ index.js
│ │ │ router.js
│ │ │
│ │ └─modules
│ │ appUsedetailModule.js
│ │ listsModule.js
│ │ statisticModule.js
│ │
│ ├─scss
│ │ index.scss
│ │
│ └─tpls
│
│
├─test
│ testIndex.js
│
└─webContent
│ favicon.ico
│ index.html
│
├─css
│ index-5067f89afc.css
│
├─js
│ bundle-588100fbe5.js
│
├─rev
│ ├─css
│ │ rev-manifest.json
│ │
│ └─js
│ rev-manifest.json
│
└─tpls
整个gulpfile.js就变成了这样:
var gulp = require('gulp'),
sass = require('gulp-sass'),
rename = require('gulp-rename'),
minifyCss = require('gulp-minify-css'),
changed = require('gulp-changed'),
uglify = require('gulp-uglify'),
debug = require('gulp-debug'),
minifyHtml = require('gulp-minify-html'),
webpack = require("webpack"),
rev = require("gulp-rev"),
revCollector = require("gulp-rev-collector"),
through = require("through2"),
del = require("del"),
ngAnnotate = require("gulp-ng-annotate"),
gulpWebpack = require('gulp-webpack');
var gulpSync = require('gulp-sync')(gulp);
var distCss = 'webContent/css',
distJs = 'webContent/js',
distRev = 'webContent/rev',
distBase = 'webContent';
gulp.task('compile-sass',function(){
return gulp.src('src/scss/*.scss')
.pipe(changed(distCss,{extension:'.css'}))
.pipe(debug({title:'debuging:'}))
.pipe(through.obj(function(chunk,encode,callback){
var delPath = chunk.cwd+"/"+distCss+"/"+chunk.relative.substring(0,chunk.relative.lastIndexOf("."))+"-*"+".css";
console.log(delPath);
del(delPath);
this.push(chunk);
callback();
}))
.pipe(sass.sync().on('error', sass.logError))
.pipe(minifyCss())
.pipe(rename(function(path){
path.basename=path.basename;
path.extname = ".css";
}))
.pipe(rev({merge: true}))
.pipe(gulp.dest(distCss))
.pipe(rev.manifest())
.pipe(gulp.dest(distRev+'/css'));
});
gulp.task('compile-js',function(){
return gulp.src('src/js/**/*.js')
.pipe(changed(distJs))
.pipe(debug({title:'debuging js:'}))
.pipe(through.obj(function(chunk,encode,callback){
var delPath = chunk.cwd+"/"+distJs+"/bundle-*"+".js";
console.log(delPath);
del(delPath);
this.push(chunk);
callback();
}))
.pipe(gulpWebpack(require('./webpack.config.js')))
.pipe(ngAnnotate())
.pipe(uglify())
.pipe(rev())
.pipe(gulp.dest(distJs))
.pipe(rev.manifest())
.pipe(gulp.dest(distRev+'/js'))
});
gulp.task('compile-html',function(){
return gulp.src('src/**/*.html')
.pipe(changed(distBase,{extension:'.html',cwd: ''}))
.pipe(debug({title:'debuging:'}))
.pipe(minifyHtml())
.pipe(rename(function(path){
path.basename=path.basename;
path.extname = ".html";
}))
.pipe(gulp.dest(distBase));
});
gulp.task('revCollectorHtml',function(){
return gulp.src(['webContent/rev/**/*.json','webContent/index.html'])//注意参数是一个数组,用【】包起来的,要不然会报无法给第二个参数创建cwd属性的错误
.pipe(revCollector({
replaceReved:true //一定要加上这一句,不然不会替换掉上一次的值
}))
.pipe(gulp.dest(distBase));
});
// gulp.task('revCollectorCss',function(){
// return gulp.src(['webContent/rev/css/*.json','webContent/css/*.css'])
// .pipe(revCollector({
// replaceReved:true //一定要加上这一句,不然不会替换掉上一次的值
// }))
// .pipe(gulp.dest(distCss));
// });
function getWatchDelFunc(type){
return function(event){
if(event.type==='deleted'){
var basePath = event.path.substring(0,event.path.lastIndexOf("src"));
var fileName = event.path.substring(event.path.lastIndexOf("\\")+1,event.path.lastIndexOf("."));
var delPath = basePath+distCss+"/"+fileName+"-*."+type;
console.log("watchDelPaths:"+delPath);
del(delPath);
}
}
}
gulp.task('watch',function(){
var watchScss = gulp.watch('src/scss/*.*',gulpSync.sync([['compile-sass'],'revCollectorHtml']));
var watchJs = gulp.watch('src/js/**/*.*',gulpSync.sync([['compile-js'],'revCollectorHtml']));
var watchHtml = gulp.watch('src/**/*.html',gulpSync.sync([['compile-html'],'revCollectorHtml']));
watchScss.on('change',getWatchDelFunc("css"));
// watchJs.on('change',getWatchDelFunc("js"));
watchHtml.on('change',getWatchDelFunc("html"));
});
gulp.task('default',gulpSync.sync([['compile-sass','compile-html','compile-js'],'revCollectorHtml','watch']));
webpack.config.js里只做了最基本的js编译:
var webpack = require("webpack");
module.exports = {
debug: true,
watch: false,
entry: "./src/js/index.js",
output: {
path: __dirname+'/webContent/js',
filename: "bundle.js"
},
module: {
loaders: [
]
},
resolve: {
},
plugins: [
]
}
gulp+webpack+angular1的一点小经验(第一部分gulp与webpack的整合)的更多相关文章
- gulp+webpack+angular1的一点小经验(第二部分webpack包起来的angular1)
又一周过去了,项目也已经做得有点模样了.收集来一些小经验,分享给大家,有疏漏之处,还望指正,海涵. 上周整合了gulp与webpack,那么工具准备差不多了,我们就开始编码吧.编码的框架就是angul ...
- gulp+webpack+angular1的一点小经验(第三部分使用一些angular1的插件ui-bootstrap与highcharts)
第一个要介绍的是我们的麻烦制造器:angular-ui-bootstrap ui-bootstrap可以有很多通用的插件给大家用,比如弹窗啊(modal),翻页控件啊(pagination),为什么说 ...
- 模仿下拉框datalist的jquery插件的一点小经验
原本项目里是用h5的新属性data-list,但是这个下拉框的数据太多,而data-list似乎没有设置高度的地方,所以写了个小插件,期间也发现了一些bug,目前这个版本算是可以一用的版本,故写一下这 ...
- Global一点小经验
Global: Global.asax 文件,有时候叫做 ASP.NET 应用程序文件,提供了一种在一个中心位置响应应用程序级或模块级事件的方法,他位于应用程序根目录下. 这个 Global.asax ...
- KInect AR沙盒制作的一点小经验
最近在微博上看到这样一条 微博 >点这看< 看起来非常有意思,就去Google了一下如何制作. 没想到这是一个开源项目,而且还告诉你如何安装 OK,接下来就说说我的制作过程. 首先,先放 ...
- Web应用程序并发问题处理的一点小经验
在web应用中,一个账户,会有N多个涉及到数字的字段.比如一个账户的金额,积分等.这些字段就涉及到增减的情况.如果是在测试环境下,靠程序员或者测试手动点击.一般是发现不了问题. 一旦上到正式环境下.有 ...
- 关于前端js拼接字符串的一点小经验
1.今天在做项目的时候遇到一个问题,就是使用onclick="xxx()" 点击事件的时候,参数如果为全数字就会出现点击无反应的问题.但是当参数为字符串或者动态内容的时候就会出现 ...
- 【Django】有关多用户管理的一点小经验分享
前言 最近,笔者因为需要开发一个系统作为毕设的展示,因此就产生了有关多用户管理的问题.在这里我把自己的需求重新阐明一下:能够通过Django自带的用户管理框架,实现多用户的管理,例如登录.登出.ses ...
- 关于cnpm的一点小bug
在实际工作中,一个项目完成后,在上线前,常常需要把代码进行压缩,一般是用gulp或者 webpack 进行压缩.(小妹是用gulp) gulp是运行在node 环境下的. 所以首先,下载并安装了nod ...
随机推荐
- m113
今天的比赛很有感触,所以来写一下题解: T1可以发现一些规律是:面积扩大的速度显然比周长扩大的速度快,然后就可以枚举周长来看能为成的面积,其实最优的情况一定是六边型的情况,通过手膜我们可以发现对于边长 ...
- Spring 应用之Spring JDBC实现
jdbcTemplate类的入门 方式一 POM.XML <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:x ...
- 替换"marquee",实现无缝滚动
js的marquee标签,可以实现元素循环滚动,但是不能无缝连接,要实现“无缝滚动”的效果必须使用js(借鉴百度),思路是使要滚动元素相对位置不断改变,上下滚动就相对top或者bottom,左右滚动就 ...
- 学习Java第一步:安装Intellij IDEA和JDK
注:其实真正学习一门新语言的第一步并不是安装开发工具,我是C#转JAVA,有一点编程经验了,所以可以直接跳过前面几步,直接上IDE. 1.下载IntelliJ IDEA [官网] http://www ...
- pat 1027 Colors in Mars(20 分)
1027 Colors in Mars(20 分) People in Mars represent the colors in their computers in a similar way as ...
- 如何解决UNMOUNTABLE BOOT VALUME
Windows error:UNMOUNTABLE BOOT VALUME 解决方法:Windows 修复工具 chkdsk命令 chkdsk D:/f ps:chkdsk 磁盘名 /f
- nyoj 101-两点距离 (数学)
101-两点距离 内存限制:64MB 时间限制:3000ms 特判: No 通过数:27 提交数:74 难度:1 题目描述: 输入两点坐标(X1,Y1),(X2,Y2)(0<=x1,x2,y1, ...
- Linux进程管理(ps、pstree、top、pidof、kill、nice、free)
进程号(Process ID,PID) 1.ps命令(process status) 无选项时只显示从当前终端当前用户的进程 ps aux 是用BSD的格式来显示 java这个进程显示的项目有:USE ...
- 百度下载给的termux是个坑
termux有两个版本,0.32以及0.64.百度提供0.32的下载,太坑爹.谷歌则是0.64的下载.32版uname -m识别为armv8l,绝对影响你进行其它linux的部署.通过atilo脚本会 ...
- C# 彻底搞懂async/await
前言 Talk is cheap, Show you the code first! private void button1_Click(object sender, EventArgs e) { ...