項目背景:一個綜合網站,開發模式爲後端嵌套數據,前端開發靜態頁面和部分組件。css
問題:gulp任務處理自動刷新、sass編譯等都是極好的。可是對於js的處理並非很好,尤爲是項目須要開發組件時候,如評論組件,須要有模版、css、js[各個模塊]。這時候選擇用gulp感受並不合適,固然能夠選擇require.js or seajs等AMD/CMD規範來開發,可是想一想項目中的組件應該是獨立於項目以外的,不依賴於任何第三方js,所以選擇去折騰webpack+gulp來搞。幾番折騰、百度以後,配置以下:html
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中有部分插件並未使用,自行選擇安裝。node
gulp配置[gulpfile.js],關於gulp使用請參考這篇文章webpack
1 var gulp = require("gulp") 2 , gutil = require("gulp-util") 3 4 , del = require("del") 5 , sass = require("gulp-sass") 6 , uglify = require('gulp-uglify') 7 , rename = require("gulp-rename") 8 9 , browserSync = require("browser-sync").create() 10 , reload = browserSync.reload 11 12 , sequence = require("run-sequence") 13 , plumber = require("gulp-plumber") 14 , watch = require("gulp-watch") 15 16 , through2 = require("through2") 17 , path = require("path") 18 , fs = require("fs") 19 , minifycss = require('gulp-minify-css') 20 , postcss = require('gulp-postcss') 21 , autoprefixer = require('autoprefixer') // Autoprefixer 爲CSS補全瀏覽器前綴 22 , cssnext = require('cssnext') // CSSNext 用下一代CSS書寫方式兼容如今瀏覽器 23 , cssgrace = require('cssgrace') // CSS Grace 讓CSS兼容舊版IE 24 , webpack = require('webpack'); 25 26 // ############################################# 27 // # init params 28 // 收集參數 29 var cwd = process.cwd(); 30 var cmdargs = process.argv.slice(2); 31 var cmdname = cmdargs.shift(); 32 var cmdopts = {}; 33 var srcpath = "./src"; 34 var distpath = "./dist"; 35 36 while (cmdargs.length) { 37 var key = cmdargs.shift().slice(2); 38 var val = cmdargs.shift(); 39 cmdopts[key] = key === "src" || key === "dist" ? normalizePath(val) : val; 40 } 41 42 // 參數配置 43 var release = cmdname === "release"; 44 var reloadTimer = null; 45 var devport = 5678; 46 var paths = { 47 src: path.join(__dirname, srcpath), 48 dist: path.join(__dirname, distpath) 49 } 50 51 function normalizePath(url) { 52 if (url.charAt(0) === "/" || url.indexOf(":") > -1) { 53 return path.normalize(url); 54 } 55 return path.normalize(path.join(cwd, url)); 56 } 57 58 function setOptions(cmd, cmdopts) { 59 if (cmd === "start") { 60 paths.src = cmdopts.src ? path.join(cmdopts.src, srcpath) : paths.src; 61 } else if (cmd === "release") { 62 paths.src = cmdopts.src ? path.join(cmdopts.src, srcpath) : paths.src; 63 paths.dist = cmdopts.dist ? cmdopts.dist : path.normalize(paths.src + "/../" + distpath); 64 } 65 } 66 67 function showUsage() { 68 console.log("Usage:\n"); 69 console.log(" gulp 顯示幫助"); 70 console.log(" gulp help 顯示幫助"); 71 console.log(" gulp start --src src 在--src目錄下自動化開發調試環境"); 72 console.log(" gulp release --src src --dist dist 構建--src線上版本到--dist目錄\n"); 73 console.log(" gulp start --src src --proxy localhost 使用gulp代理localhost請求,而且實時監聽src文件修改"); 74 } 75 76 // ############################################# 77 // # default tasks 78 79 // # clean path 80 gulp.task("clean:dist", function() { 81 return del([paths.dist], { 82 force: true 83 }); 84 }); 85 86 // # 編譯css 87 gulp.task("sass", function() { 88 var base = paths.src; 89 var dest = base; 90 var processors = [ 91 autoprefixer({ 92 browsers: ['last 3 version', '> 5%', 'Android >= 4.0', 'iOS >= 7'], 93 cascade: false, //是否美化屬性值 默認:true 像這樣: 94 remove: true //是否去掉沒必要要的前綴 默認:true 95 }), 96 // cssnext(), 97 // cssgrace 98 ]; 99 return gulp.src(base + "/**/*.scss", { 100 base: base 101 }) 102 .pipe(plumber()) 103 .pipe(sass({ 104 precision: 2, 105 outputStyle: release ? "compressed" : "expanded" 106 //sourceComments: release ? false : true 107 }) 108 .on("error", sass.logError)) 109 .pipe(postcss(processors)) 110 .pipe(gulp.dest(dest)); 111 }); 112 // 編譯單個css 113 function parseSingleFile(file) { 114 var base = paths.src; 115 var dest = base; 116 var processors = [ 117 autoprefixer({ 118 browsers: ['last 3 version', '> 5%', 'Android >= 4.0', 'iOS >= 7'], 119 cascade: false, //是否美化屬性值 默認:true 像這樣: 120 remove: true //是否去掉沒必要要的前綴 默認:true 121 }), 122 // cssnext(), 123 // cssgrace 124 ]; 125 return gulp.src(file, { 126 base: base 127 }) 128 .pipe(plumber()) 129 .pipe(sass({ 130 precision: 2, 131 outputStyle: release ? "compressed" : "expanded" 132 //sourceComments: release ? false : true 133 }) 134 .on("error", sass.logError)) 135 .pipe(postcss(processors)) 136 .pipe(gulp.dest(dest)); 137 } 138 139 140 // # 壓縮js 141 gulp.task("uglify", function() { 142 var base = paths.src; 143 var dest = paths.dist; 144 return gulp.src([ 145 base + "/**/*.js", 146 "!" + base +"/**/*-component/**", 147 "!" + base + "/**/*min.js" // 排除壓縮min.js文件 148 ], { 149 base: base 150 }) 151 .pipe(plumber()) 152 .pipe(uglify()) 153 .pipe(gulp.dest(dest)); 154 }); 155 156 // # 調用webpack處理component 157 function parseComponentToWebpack(path){ 158 var webpackConfig = require('./webpack.config.js'); 159 // 靈活處理output位置,將js文件生成在component同級目錄 160 // 將**/*-component/xx.js路徑替換爲** 161 // var outputPath = path.replace(/\/[^\/]+\/[^\/]+$/,''); 162 var outputPath = path.replace(/\/([^\/]+)-component\/[^\/]+$/,''); 163 var filename = RegExp.$1; 164 webpackConfig.entry = {}; 165 webpackConfig.entry[filename] = path+'/../index.js'; 166 // windows上webpack不認識D:/xxx路徑,替換爲D:\\xxx路徑 167 outputPath = outputPath.replace('/','\\\\'); 168 webpackConfig.output.path = outputPath; 169 return webpack(webpackConfig, function(err, stats) { 170 console.log(stats.toString()); 171 }); 172 } 173 174 175 // # 壓縮css 176 gulp.task("mincss", function() { 177 var base = paths.src; 178 var dest = paths.dist; 179 gulp.src(dest + '/**/*.css') 180 .pipe(minifycss()) 181 .on('error', function(e) { 182 console.log(e) 183 }) 184 .pipe(gulp.dest(dest)); 185 }); 186 187 // # 複製靜態資源 188 gulp.task("copy:dist", function() { 189 var base = paths.src; 190 var dest = paths.dist; 191 // 複製min.js文件 192 gulp.src([ 193 base + "/**/*min.js" 194 ], { 195 base: base 196 }) 197 .pipe(gulp.dest(dest)); 198 return gulp.src([ 199 base + "/**/*", 200 "!" + base +"/**/*-component", 201 "!" + base +"/**/*-component/**", 202 "!" + base + "/**/*.js", 203 "!" + base + "/**/*.scss" 204 ], { 205 base: base 206 }) 207 .pipe(gulp.dest(dest)); 208 }); 209 210 211 // # serv & watch 212 gulp.task("server", function() { 213 // start server 214 browserSync.init({ 215 ui: false, 216 notify: false, 217 port: devport, 218 // 設置代理請求 219 proxy: cmdopts.proxy, 220 server: !cmdopts.proxy ? { 221 baseDir: paths.src 222 } : false 223 }); 224 225 // # watch src資源, 調用相關任務預處理 226 // # 刷新瀏覽器 227 // # 限制瀏覽器刷新頻率 228 watch(paths.src + "/**/*", function(obj) { 229 var url = obj.path.replace(/\\/g, "/"); 230 var absurl = url; 231 url = path.relative(paths.src, url).replace(/\\/g, "/"); 232 console.log("[KS] " + absurl); 233 234 // skip scss & css 235 if (!/\.scss$/.test(url) && !/\.css$/.test(url)) { 236 if (/.+-component\/.+\.js$/.test(url)) { 237 // 評論組件,調用webpack 238 console.log("[webpack] "+absurl); 239 parseComponentToWebpack(absurl); 240 return; 241 } 242 if (reloadTimer) { 243 clearTimeout(reloadTimer); 244 } 245 reloadTimer = setTimeout(reload, 1000); 246 }else if(/\.scss$/.test(url)){ 247 // sass任務 248 parseSingleFile(absurl) 249 // 無刷新加載css 250 .pipe(reload({ 251 stream: true 252 })); 253 // sequence("sass"); 254 } 255 }); 256 }); 257 258 259 // ############################################# 260 // # public task 261 262 gulp.task("default", showUsage); 263 gulp.task("help", showUsage); 264 265 gulp.task("start", function(cb) { 266 release = false; 267 setOptions("start", cmdopts); 268 sequence("sass", "server", cb); 269 }); 270 271 gulp.task("release", function(cb) { 272 release = true; 273 setOptions("release", cmdopts); 274 sequence("clean:dist", "copy:dist", ["mincss", "uglify"], cb); 275 });
webpack配置(webpack.config.js),webpack配置參考es6
1 var webpack = require('webpack'); 2 3 module.exports = { 4 // devtool: 'eval-source-map', 5 devtool: false, 6 entry: { 7 "component-comment": __dirname + "/src/assets/comment/component/index.js" 8 }, 9 output: { 10 // path: __dirname + "/src/assets/comment", 11 path: __dirname + "/dist/component", 12 filename: "[name].js" 13 }, 14 15 module: { 16 rules: [{ 17 test: /\.json$/, 18 loader: "json-loader" 19 }, 20 { 21 test: /\.js$/, 22 exclude: /node_modules/, 23 loader: 'babel-loader', //在webpack的module部分的loaders裏進行配置便可 24 /*query: { 25 presets: ['es2015'] 26 }*/ 27 query: { 28 presets: [ 29 ['es2015', { 30 'modules': false //babel不編譯es6的模塊加載,讓webpack支持Tree-shaking 31 }] 32 ] 33 } 34 }, 35 ] 36 }, 37 38 }
以上配置webpack將單獨處理component目錄中的js文件,並在component同級目錄生成文件夾相同名字的js文件(如:'./component-comment-component/' 文件夾對應的js文件爲 './component-comment.js')。web
如下是個人文件結構ajax
1 src 2 app 3 *.html //html目錄 4 assets //靜態資源目錄 5 component-comment-component //評論組件 6 images //評論組件所用圖片 7 component //組件模塊 8 common.js //公用方法,如ajax、jsonp、extend等方法 9 defaultConfig.js //默認配置 10 emoticon.js //表情模塊,如獲取服務端表情資源,渲染表情等 11 index.js //主模塊,如獲取評論、發表評論、點贊、回覆、舉報等 12 selector.js //選擇器方法,模擬jQuery封裝 13 template.js //模版 14 component-comment.js //webpack編譯component目錄的js 15 component-comment.scss //評論樣式表 16 component-comment.css //編譯的sass文件 17 css //項目其餘sass|css資源 18 images //項目圖片文件 19 js //項目的其餘js
以上只是一個簡單的使用案例,針對不一樣結構須要做出不一樣調整。json