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

问题: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

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

gulp+webpack多页应用开发,webpack仅处理打包js的更多相关文章

  1. 做一个gulp+webpack+vue的单页应用开发架子

    1.目标 最近项目上的事情不多,根据我自己的开发习惯,决定开发一些简单的开发架子,方便以后事情多的时候直接套用.本文讲的一个gulp+webpack+vue的单页应用架子,想要达到的目的: 可以通过命 ...

  2. webpack+express多页站点开发

    学习了webpack门级的教程后,觉得可能是专门为单页应用而量身打造的,比如webpack+react.webpack+vue等,都可以解决各种资源的依赖加载.打包的问题.甚至css都是打包在js里去 ...

  3. 利用免费cdn加速webpack单页应用

    回顾现状 在之前的学习过程中,react单页应用经过webpack打包之后会输出大概如下的目录结构,它就是站点的所有前端组成了:   1 2 3 4 5 6 MacBook-Pro:output ba ...

  4. 基于webpack的前端工程化开发解决方案探索(一):动态生成HTML(转)

    1.什么是工程化开发 软件工程的工程化开发概念由来已久,但对于前端开发来说,我们没有像VS或者eclipse这样量身打造的IDE,因为在大多数人眼中,前端代码无需编译,因此只要一个浏览器来运行调试就行 ...

  5. vue(9)—— 组件化开发 - webpack(3)

    前面两个终于把webpack相关配置解析完了.现在终于进入vue的开发了 vue组件化开发预热 前期准备 创建如下项目: app.js: footer.js: main.js: webpack.con ...

  6. 微服务项目开发学成在线_Vue.js与Webpack

    Vue.js 1.Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式框架.自底向上逐层应用:作为渐进式框架要实现的目标就是方便项目增量开发. 渐进式框架:Progress ...

  7. webpack+react+redux+es6开发模式

    一.预备知识 node, npm, react, redux, es6, webpack 二.学习资源 ECMAScript 6入门 React和Redux的连接react-redux Redux 入 ...

  8. [webpack] 配置react+es6开发环境

    写在前面 每次开新项目都要重新安装需要的包,简单记录一下. 以下仅包含最简单的功能: 编译react 编译es6 打包src中入口文件index.js至dist webpack配置react+es6开 ...

  9. webpack 教程 那些事儿06-gulp+webpack多页

    本篇主要讲述用gulp+webpack构建多页应用 折腾到现在,项目还必须要进行,.vue文件必须要加载,也就是webpack必须引入.时间不多了,抛弃上个方案之后,只能牺牲热加载性能,用gulp+w ...

随机推荐

  1. Linux RedHat 7 配置本地 YUM源

    尽管RPM安装方法能够帮助用户查询软件相关的依赖关系,但是还是需要安装人员自己来解决,而且有些大型软件可能与数十个程序都有依赖关系,在这种情况下安装软件事件非常痛苦和耗费事件的事情,而Yum软件仓库可 ...

  2. Net Core 自定义 Middleware 加密解密

    前言:第一次写文章,有问题请轻喷 当前使用 Net Core 版本 2.1.3 我们经常在开发中需要把实体的主键 Id 传输到前端,但是在Get的时候又不想让前端能看到明文,我们通常会加密这些数据,所 ...

  3. OpenFace 调试记录

    1.OpenFace 是 卡耐基梅陇(CMU)大学的一个图像+机器学习项目,整体程序包含:人脸发现,特征提取,特征神经网络训练,人脸识别这四部分. github   https://github.co ...

  4. 关于创建Web图像时应记住的五个要素

    1. 格式与下载速度 当前,Web上用的最广泛的三种格式是GIF.PNG和JPEG.我们的目标是选择质量最高,同时文件最小的格式. WebP图像格式 谷歌建立了另一种图像格式,名为WebP. 这种格式 ...

  5. vue设置多个入口

    做VUE项目时,有时想做多个入口来解决某些问题. 在根目录下的复制一份index.html,名称随便你命名,当然,你也可以都是放到一个文件夹下,我的就叫index1.html 然后在App.vue也复 ...

  6. 珠宝juelrye英语juelrye宝石

    jewellery (usually uncountable, plural jewelleries) 1.(British spelling, Canadian) Collectively, per ...

  7. day 03 作业 预科

    目录 作业 1.简述变量的组成 2.简述变量名的命名规范 3.简述注释的作用 4.使用turtle库构造一幅图,贴在markdown文档中 作业 1.简述变量的组成 变量由变量名.赋值符号.变量值所组 ...

  8. Mybatis环境搭建:自学随笔

    环境:IDEA  MySQL 1.建立maven工程,导入坐标:编辑pom.xml,建立mybatis约束. 在https://mybatis.org/mybatis-3/zh/getting-sta ...

  9. 关于git报 warning: LF will be replaced by CRLF in README.md.的警告的解决办法

    在使用git把代码上传至仓库时,会有下面这种警告: 虽然说是警告,但是看着真的很碍眼啊,特别是有强迫症的人就更难受了. 输入这一行命令就可以完美解决了 git config core.autocrlf ...

  10. thrift简单示例 (go语言)

    这个thrift的简单示例来自于官网 (http://thrift.apache.org/tutorial/go), 因为官方提供的例子简单易懂, 所以没有必要额外考虑新的例子. 关于安装的教程, 可 ...