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"
  }
}
View Code

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

 

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

  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配置参考

 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')。

以下是我的文件结构

 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

 

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

posted @ 2017-05-09 10:51  极·简  Views(3512)  Comments(0Edit  收藏  举报