gulp+webpack多页应用开发,webpack仅处理打包js
项目背景:一个综合网站,开发模式为后端嵌套数据,前端开发静态页面和部分组件。
问题: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的更多相关文章
- 做一个gulp+webpack+vue的单页应用开发架子
1.目标 最近项目上的事情不多,根据我自己的开发习惯,决定开发一些简单的开发架子,方便以后事情多的时候直接套用.本文讲的一个gulp+webpack+vue的单页应用架子,想要达到的目的: 可以通过命 ...
- webpack+express多页站点开发
学习了webpack门级的教程后,觉得可能是专门为单页应用而量身打造的,比如webpack+react.webpack+vue等,都可以解决各种资源的依赖加载.打包的问题.甚至css都是打包在js里去 ...
- 利用免费cdn加速webpack单页应用
回顾现状 在之前的学习过程中,react单页应用经过webpack打包之后会输出大概如下的目录结构,它就是站点的所有前端组成了: 1 2 3 4 5 6 MacBook-Pro:output ba ...
- 基于webpack的前端工程化开发解决方案探索(一):动态生成HTML(转)
1.什么是工程化开发 软件工程的工程化开发概念由来已久,但对于前端开发来说,我们没有像VS或者eclipse这样量身打造的IDE,因为在大多数人眼中,前端代码无需编译,因此只要一个浏览器来运行调试就行 ...
- vue(9)—— 组件化开发 - webpack(3)
前面两个终于把webpack相关配置解析完了.现在终于进入vue的开发了 vue组件化开发预热 前期准备 创建如下项目: app.js: footer.js: main.js: webpack.con ...
- 微服务项目开发学成在线_Vue.js与Webpack
Vue.js 1.Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式框架.自底向上逐层应用:作为渐进式框架要实现的目标就是方便项目增量开发. 渐进式框架:Progress ...
- webpack+react+redux+es6开发模式
一.预备知识 node, npm, react, redux, es6, webpack 二.学习资源 ECMAScript 6入门 React和Redux的连接react-redux Redux 入 ...
- [webpack] 配置react+es6开发环境
写在前面 每次开新项目都要重新安装需要的包,简单记录一下. 以下仅包含最简单的功能: 编译react 编译es6 打包src中入口文件index.js至dist webpack配置react+es6开 ...
- webpack 教程 那些事儿06-gulp+webpack多页
本篇主要讲述用gulp+webpack构建多页应用 折腾到现在,项目还必须要进行,.vue文件必须要加载,也就是webpack必须引入.时间不多了,抛弃上个方案之后,只能牺牲热加载性能,用gulp+w ...
随机推荐
- IOWebSocketChannel.connect handle errors
https://github.com/dart-lang/web_socket_channel/issues/38 yes, my workaround is to create a WebSocke ...
- 英文FRAUNCE法国FRAUNCE单词
France Alternative forms Fraunce In Fraunce, the inhabitants of one city were driven out and forced ...
- leetcode 学习心得 (3)
源代码地址:https://github.com/hopebo/hopelee 语言:C++ 517. Super Washing Machines You have n super washing ...
- Linux 磁盘配额(XFS & EXT4)
若是在Linux中搭建了FTP服务器,为了安全性,就要考虑磁盘配额,以防服务器磁盘空间被恶意占满. 磁盘配额概述 1.作用范围:只在指定的分区有效. 2.限制对象:主要针对用户.组进行限制,对组账号限 ...
- Vi 和 Vim 编辑器详细使用方法
学习linux的一项必会技能,熟练使用vi/vim编辑器那便最重要的了.不过一堆操作看的也是太头疼了,以下整理了些常用到的命令. 工作模式 vi编辑界面有三种不同的工作模式,分别为命令模式.输入模式. ...
- UBOOT2016.05 看门狗
硬件平台 AM335X UBOOT 2016.05 在UBOOT中关看门狗,需要修改屏蔽这两处代码 init_sequence_r->board_init->hw_watchdog_in ...
- centos下安装opencv
根据项目需要,安装opencv并提供给开发使用,并且使用opencv提供python3的API接口.虽然不知道是个啥,还是简单了解下. opencv是什么? OpenCV的全称是Open Source ...
- 网络空间安全基础篇(2)----wireshark
wireshrak是一款通过本地端口,来抓取通过以太网获取的文件包,包括SMB HTTP FTP TELNET 等包 在网络安全比赛中最常用的就是HTTP协议,TELNET协议,FTP协议,SMB协议 ...
- CH340g使用说明详解
用串口和CH340模块都可以让计算机和单片机进行通信,但是使用CH340更加方便,省去了使用串口的麻烦 CH340是一个USB总线的转接芯片,实现USB转串口.USB转IrDA红外或者USB转打印口. ...
- 优化nginx数据包头缓存
例子:414错误,网址太长. 长网址访问例子: 以下脚本会生成一个长网址并访问,导致414长网址报错. [root@proxy ~]#vim nginx_test.sh #!/bin/bash URL ...