项目背景:一个综合网站,开发模式为后端嵌套数据,前端开发静态页面和部分组件。

问题:gulp任务处理自动刷新、sass编译等都是极好的。但是对于js的处理并不是很好,尤其是项目需要开发组件时候,如评论组件,需要有模版、css、js[各个模块]。这时候选择用gulp感觉并不合适,当然可以选择require.js or seajs等AMD/CMD规范来开发,但是想想项目中的组件应该是独立于项目之外的,不依赖于任何第三方js,因此选择去折腾webpack+gulp来搞。几番折腾、百度之后,配置如下:

package.js

{
"name": "work",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"devDependencies": {
"autoprefixer": "^6.3.6",
"autoprefixer-core": "^6.0.1",
"babel-core": "^6.24.1",
"babel-loader": "^7.0.0",
"babel-preset-es2015": "^6.24.1",
"browser-sync": "^2.13.0",
"cssgrace": "^3.0.0",
"cssnext": "^1.8.4",
"del": "^2.2.1",
"extract-text-webpack-plugin": "^2.1.0",
"fs": "^0.0.2",
"gulp": "^3.9.1",
"gulp-babel": "^6.1.2",
"gulp-concat": "^2.6.0",
"gulp-htmlmin": "^2.0.0",
"gulp-imagemin": "^3.0.1",
"gulp-jshint": "^2.0.1",
"gulp-less": "^3.1.0",
"gulp-livereload": "^3.8.1",
"gulp-minify-css": "^1.2.4",
"gulp-notify": "^2.2.0",
"gulp-plumber": "^1.1.0",
"gulp-postcss": "^6.1.1",
"gulp-rename": "^1.2.2",
"gulp-sass": "^2.3.2",
"gulp-uglify": "^1.5.3",
"gulp-util": "^3.0.7",
"gulp-watch": "^4.3.8",
"gulp-webpack": "^1.5.0",
"imagemin-jpegtran": "^5.0.2",
"imagemin-pngcrush": "^5.0.0",
"jshint": "^2.9.2",
"json-loader": "^0.5.4",
"node-sass": "^4.5.2",
"path": "^0.12.7",
"run-sequence": "^1.2.1",
"through2": "^2.0.1",
"webpack": "^2.4.1"
}
}

package中有部分插件并未使用,自行选择安装。

gulp配置[gulpfile.js],关于gulp使用请参考这篇文章

 var gulp = require("gulp")
, gutil = require("gulp-util") , del = require("del")
, sass = require("gulp-sass")
, uglify = require('gulp-uglify')
, rename = require("gulp-rename") , browserSync = require("browser-sync").create()
, reload = browserSync.reload , sequence = require("run-sequence")
, plumber = require("gulp-plumber")
, watch = require("gulp-watch") , through2 = require("through2")
, path = require("path")
, fs = require("fs")
, minifycss = require('gulp-minify-css')
, postcss = require('gulp-postcss')
, autoprefixer = require('autoprefixer') // Autoprefixer 为CSS补全浏览器前缀
, cssnext = require('cssnext') // CSSNext 用下一代CSS书写方式兼容现在浏览器
, cssgrace = require('cssgrace') // CSS Grace 让CSS兼容旧版IE
, webpack = require('webpack'); // #############################################
// # init params
// 收集参数
var cwd = process.cwd();
var cmdargs = process.argv.slice(2);
var cmdname = cmdargs.shift();
var cmdopts = {};
var srcpath = "./src";
var distpath = "./dist"; while (cmdargs.length) {
var key = cmdargs.shift().slice(2);
var val = cmdargs.shift();
cmdopts[key] = key === "src" || key === "dist" ? normalizePath(val) : val;
} // 参数配置
var release = cmdname === "release";
var reloadTimer = null;
var devport = 5678;
var paths = {
src: path.join(__dirname, srcpath),
dist: path.join(__dirname, distpath)
} function normalizePath(url) {
if (url.charAt(0) === "/" || url.indexOf(":") > -1) {
return path.normalize(url);
}
return path.normalize(path.join(cwd, url));
} function setOptions(cmd, cmdopts) {
if (cmd === "start") {
paths.src = cmdopts.src ? path.join(cmdopts.src, srcpath) : paths.src;
} else if (cmd === "release") {
paths.src = cmdopts.src ? path.join(cmdopts.src, srcpath) : paths.src;
paths.dist = cmdopts.dist ? cmdopts.dist : path.normalize(paths.src + "/../" + distpath);
}
} function showUsage() {
console.log("Usage:\n");
console.log(" gulp 显示帮助");
console.log(" gulp help 显示帮助");
console.log(" gulp start --src src 在--src目录下自动化开发调试环境");
console.log(" gulp release --src src --dist dist 构建--src线上版本到--dist目录\n");
console.log(" gulp start --src src --proxy localhost 使用gulp代理localhost请求,并且实时监听src文件修改");
} // #############################################
// # default tasks // # clean path
gulp.task("clean:dist", function() {
return del([paths.dist], {
force: true
});
}); // # 编译css
gulp.task("sass", function() {
var base = paths.src;
var dest = base;
var processors = [
autoprefixer({
browsers: ['last 3 version', '> 5%', 'Android >= 4.0', 'iOS >= 7'],
cascade: false, //是否美化属性值 默认:true 像这样:
remove: true //是否去掉不必要的前缀 默认:true
}),
// cssnext(),
// cssgrace
];
return gulp.src(base + "/**/*.scss", {
base: base
})
.pipe(plumber())
.pipe(sass({
precision: 2,
outputStyle: release ? "compressed" : "expanded"
//sourceComments: release ? false : true
})
.on("error", sass.logError))
.pipe(postcss(processors))
.pipe(gulp.dest(dest));
});
// 编译单个css
function parseSingleFile(file) {
var base = paths.src;
var dest = base;
var processors = [
autoprefixer({
browsers: ['last 3 version', '> 5%', 'Android >= 4.0', 'iOS >= 7'],
cascade: false, //是否美化属性值 默认:true 像这样:
remove: true //是否去掉不必要的前缀 默认:true
}),
// cssnext(),
// cssgrace
];
return gulp.src(file, {
base: base
})
.pipe(plumber())
.pipe(sass({
precision: 2,
outputStyle: release ? "compressed" : "expanded"
//sourceComments: release ? false : true
})
.on("error", sass.logError))
.pipe(postcss(processors))
.pipe(gulp.dest(dest));
} // # 压缩js
gulp.task("uglify", function() {
var base = paths.src;
var dest = paths.dist;
return gulp.src([
base + "/**/*.js",
"!" + base +"/**/*-component/**",
"!" + base + "/**/*min.js" // 排除压缩min.js文件
], {
base: base
})
.pipe(plumber())
.pipe(uglify())
.pipe(gulp.dest(dest));
}); // # 调用webpack处理component
function parseComponentToWebpack(path){
var webpackConfig = require('./webpack.config.js');
// 灵活处理output位置,将js文件生成在component同级目录
// 将**/*-component/xx.js路径替换为**
// var outputPath = path.replace(/\/[^\/]+\/[^\/]+$/,'');
var outputPath = path.replace(/\/([^\/]+)-component\/[^\/]+$/,'');
var filename = RegExp.$1;
webpackConfig.entry = {};
webpackConfig.entry[filename] = path+'/../index.js';
// windows上webpack不认识D:/xxx路径,替换为D:\\xxx路径
outputPath = outputPath.replace('/','\\\\');
webpackConfig.output.path = outputPath;
return webpack(webpackConfig, function(err, stats) {
console.log(stats.toString());
});
} // # 压缩css
gulp.task("mincss", function() {
var base = paths.src;
var dest = paths.dist;
gulp.src(dest + '/**/*.css')
.pipe(minifycss())
.on('error', function(e) {
console.log(e)
})
.pipe(gulp.dest(dest));
}); // # 复制静态资源
gulp.task("copy:dist", function() {
var base = paths.src;
var dest = paths.dist;
// 复制min.js文件
gulp.src([
base + "/**/*min.js"
], {
base: base
})
.pipe(gulp.dest(dest));
return gulp.src([
base + "/**/*",
"!" + base +"/**/*-component",
"!" + base +"/**/*-component/**",
"!" + base + "/**/*.js",
"!" + base + "/**/*.scss"
], {
base: base
})
.pipe(gulp.dest(dest));
}); // # serv & watch
gulp.task("server", function() {
// start server
browserSync.init({
ui: false,
notify: false,
port: devport,
// 设置代理请求
proxy: cmdopts.proxy,
server: !cmdopts.proxy ? {
baseDir: paths.src
} : false
}); // # watch src资源, 调用相关任务预处理
// # 刷新浏览器
// # 限制浏览器刷新频率
watch(paths.src + "/**/*", function(obj) {
var url = obj.path.replace(/\\/g, "/");
var absurl = url;
url = path.relative(paths.src, url).replace(/\\/g, "/");
console.log("[KS] " + absurl); // skip scss & css
if (!/\.scss$/.test(url) && !/\.css$/.test(url)) {
if (/.+-component\/.+\.js$/.test(url)) {
// 评论组件,调用webpack
console.log("[webpack] "+absurl);
parseComponentToWebpack(absurl);
return;
}
if (reloadTimer) {
clearTimeout(reloadTimer);
}
reloadTimer = setTimeout(reload, 1000);
}else if(/\.scss$/.test(url)){
// sass任务
parseSingleFile(absurl)
// 无刷新加载css
.pipe(reload({
stream: true
}));
// sequence("sass");
}
});
}); // #############################################
// # public task gulp.task("default", showUsage);
gulp.task("help", showUsage); gulp.task("start", function(cb) {
release = false;
setOptions("start", cmdopts);
sequence("sass", "server", cb);
}); gulp.task("release", function(cb) {
release = true;
setOptions("release", cmdopts);
sequence("clean:dist", "copy:dist", ["mincss", "uglify"], cb);
});

webpack配置(webpack.config.js),webpack配置参考

 var webpack = require('webpack');

 module.exports = {
// devtool: 'eval-source-map',
devtool: false,
entry: {
"component-comment": __dirname + "/src/assets/comment/component/index.js"
},
output: {
// path: __dirname + "/src/assets/comment",
path: __dirname + "/dist/component",
filename: "[name].js"
}, module: {
rules: [{
test: /\.json$/,
loader: "json-loader"
},
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader', //在webpack的module部分的loaders里进行配置即可
/*query: {
presets: ['es2015']
}*/
query: {
presets: [
['es2015', {
'modules': false //babel不编译es6的模块加载,让webpack支持Tree-shaking
}]
]
}
},
]
}, }

以上配置webpack将单独处理component目录中的js文件,并在component同级目录生成文件夹相同名字的js文件(如:'./component-comment-component/' 文件夹对应的js文件为 './component-comment.js')。

以下是我的文件结构

 src
app
*.html //html目录
assets //静态资源目录
component-comment-component //评论组件
images //评论组件所用图片
component //组件模块
common.js //公用方法,如ajax、jsonp、extend等方法
defaultConfig.js //默认配置
emoticon.js //表情模块,如获取服务端表情资源,渲染表情等
index.js //主模块,如获取评论、发表评论、点赞、回复、举报等
selector.js //选择器方法,模拟jQuery封装
template.js //模版
component-comment.js //webpack编译component目录的js
component-comment.scss //评论样式表
component-comment.css //编译的sass文件
css //项目其他sass|css资源
images //项目图片文件
js //项目的其他js

以上只是一个简单的使用案例,针对不同结构需要作出不同调整。

最新文章

  1. 学习 AppFuse
  2. Redis学习——链表源码分析
  3. Leetcode Spiral Matrix II
  4. 黑马程序员——JAVA基础之数组
  5. HDU 5969 最大的位或 【贪心】 (2016年中国大学生程序设计竞赛(合肥))
  6. 使用单例模式实现自己的HttpClient工具类
  7. 知方可补不足~CSS中的几个伪元素
  8. android设备之间屏幕共享
  9. Unity 5.X扩展编辑器之打包assetbundle
  10. CSS3_移动端_开机动画
  11. mongodb非关系型数据库
  12. AngularJS ui-router刷新子页面路由
  13. CentOS中利用Docker安装Redis
  14. fullpage.js与animate.css搭配使用
  15. 听说 —— beta冲刺总结
  16. u-boot中网口处理--硬件部分
  17. MongoDB分片介绍
  18. Javascript中的闭包(转载)
  19. 521. Longest Uncommon Subsequence I【easy】
  20. 使用vue-router beforEach实现判断用户登录跳转路由筛选功能

热门文章

  1. 玩转dockerfile
  2. 2019 顺网游戏java面试笔试题 (含面试题解析)
  3. 2019 讯飞java面试笔试题 (含面试题解析)
  4. kafka消费者问题
  5. Html-元素类型笔记
  6. jstorm了解—应用场景
  7. ssm的maven项目启动tomcat时报错,Cannot find class: XXXX解决办法
  8. 02-CSS常用样式
  9. 四、Linux_用户切换
  10. AXURE RP EXTENSION For Chrome----解决办法