webpack、grunt、gulp区别
grunt和gulp:任务执行程序,根据配置文件中匹配规则执行任务,不能做到按需加载,虽然能配置babel对es6进行降级,但是不能预加载babel垫片
webpack:模块打包程序,更像一套前端工程化解决方案。能通过智能分析对js进行模块划分,按需加载,并且能预加载babel垫片,其能利用强大插件机制,解决前端静态资源依赖管理的问题。
webpack与grunt、gulp运行机制
# grunt gulp 思路
【遍历源文件】->【匹配规则】->【打包】
做不到按需加载,对打包的资源,是否用到,打包过程不关心。
# webpack
【入口】->【模块依赖加载】->【依赖分析】->【打包】
在加载、分析、打包的过程中,可以针对性的做一些解决方案。比如:code split(拆分公共代码)
Grunt和Gulp的工作方式是:在一个配置文件中,指明对某些文件进行类似编译,组合,压缩等任务的具体步骤,工具之后可以自动替你完成这些任务
Webpack的工作方式是:把你的项目当做一个整体,通过一个给定的主文件(如:index.js),Webpack将从这个文件开始找到你的项目的所有依赖文件,使用loaders处理它们,最后打包为一个(或多个)浏览器可识别的JavaScript文件。
Grunt与Gulp性能比较
Grunt: 每个任务处理完成后存放在本地磁盘.tmp目录中,有本地磁盘的I/O操作,会导致打包速度比较慢。
Gulp: gulp与grunt都是按任务执行,gulp有一个文件流的概念。每一步构建的结果并不会存在本地磁盘,而是保存在内存中,下一个步骤是可以使用上一个步骤的内存,大大增加了打包的速度。
配置文件示例
grunt配置文件示例(Gruntfile.js):
1 module.exports = function (grunt) { 2 \'use strict\'; 3 //导入/加载使用到的任务插件 4 grunt.loadNpmTasks(\'grunt-contrib-less\'); 5 grunt.loadNpmTasks(\'grunt-contrib-cssmin\'); 6 grunt.loadNpmTasks(\'grunt-contrib-uglify\'); 7 grunt.loadNpmTasks(\'grunt-contrib-concat\'); 8 grunt.loadNpmTasks(\'grunt-contrib-jshint\'); 9 grunt.loadNpmTasks(\'grunt-contrib-qunit\'); 10 grunt.loadNpmTasks(\'grunt-contrib-watch\'); 11 grunt.loadNpmTasks(\'grunt-contrib-htmlmin\'); 12 grunt.loadNpmTasks(\'grunt-contrib-imagemin\'); 13 //grunt config 14 grunt.initConfig({ 15 //从package.json中读取项目元数据(项目名...) 16 pkg: grunt.file.readJSON(\'package.json\'), 17 //less编译 18 less: { 19 development: { 20 //除了options,其它key可随意起 执行任务时都会迭代执行 21 files: [{ 22 //expand设置为true:启用下面选项 23 expand: true, 24 //less源文件基路径 25 cwd: \'src/less\', 26 //less匹配模式 27 src: [\'*.less\'], 28 //css目标文件基路径 29 dest: \'src/css\', 30 //生成文件的扩展名:css 31 ext: \'.css\' 32 }] 33 } 34 }, 35 //css压缩 36 cssmin: { 37 //可配置选项 38 options: { 39 //文件头部生成的注释:包名+时间 <%= js代码 %> 40 banner: \'/*! <%= pkg.name %> <%= grunt.template.today("yyyy-mm-dd") %> */\n\' 41 }, 42 static_mappings: { 43 files: [{ 44 expand: true, 45 cwd: \'src/css\', 46 src: \'*.css\', 47 dest: \'src/css/\', 48 ext: \'.min.css\' 49 }] 50 } 51 }, 52 //压缩HTML 53 htmlmin: { 54 options: { 55 removeComments: true, //移除注释 56 removeCommentsFromCDATA: true, //移除来自字符数据的注释 57 collapseWhitespace: true, //无用空格 58 collapseBooleanAttributes: true, //失败的布尔属性 59 // // removeAttributeQuotes: true,//移除属性引号 有些属性不可移走引号 60 // removeRedundantAttributes: true,//移除多余的属性 61 // useShortDoctype: true,//使用短的跟元素 62 removeEmptyAttributes: true //移除空的属性 63 // removeOptionalTags: true,//移除可选附加标签 64 }, 65 //yasuo 是随意起的任务目标名 因为任务开始会迭代全部目标 因此可随意起 66 yasuo: { 67 expand: true, 68 cwd: \'src/pages\', 69 src: [\'*.html\'], 70 dest: \'dist/pages\', 71 ext: \'.html\' 72 } 73 }, 74 //压缩图片 75 imagemin: { 76 dist: { 77 options: { 78 optimizationLevel: 3 //定义 PNG 图片优化水平 79 }, 80 files: [{ 81 expand: true, 82 cwd: \'src/images\', // 图片在imagemin目录下 83 src: [\'**/*.{png,jpg,jpeg}\'], // 优化 imagemin 目录下所有 png/jpg/jpeg 图片 84 dest: \'dist/images\' // 优化后的图片保存位置,覆盖旧图片,并且不作提示 85 }] 86 } 87 }, 88 //js语法检查 89 jshint: { 90 //要检查的文件 91 files: [\'src/js/*.js\'], 92 options: { 93 globals: { 94 jQuery: true, 95 console: true, 96 module: true 97 } 98 } 99 }, 100 //js压缩 101 uglify: { 102 options: { 103 banner: \'/*! <%= pkg.name %> <%= grunt.template.today("yyyy-mm-dd") %> */\n\', 104 //压缩时去除console.log 105 compress: { 106 drop_console: true 107 } 108 }, 109 static_mappings: { 110 files: [{ 111 expand: true, 112 cwd: \'src/js\', 113 src: \'*.js\', 114 dest: \'src/js/min\', 115 ext: \'.min.js\' 116 }] 117 } 118 }, 119 //合并压缩的js和css 120 concat: { 121 //合并js 122 distjs: { 123 //源文件路径+匹配模式 124 src: [\'src/js/min/*.min.js\'], 125 //合并后的文件 126 dest: \'dist/js/app.js\' 127 }, 128 //合并css 129 distcss: { 130 src: [\'src/css/*.min.css\'], 131 dest: \'dist/css/app.css\' 132 } 133 }, 134 //代码测试 135 qunit: { 136 //要测试文件 137 files: [\'dist/pages/*.html\'] 138 }, 139 //监听器 140 watch: { 141 //监听文件变化并执行相应任务 142 //表示监听src下的所有目录下的所有文件(也可以写成模板形式:<%= jshint.files %>:相当于src/js/*.js) 143 files: [\'src/**/*.*\'], 144 //文件变化时执行的任务(按顺序执行) 145 task: [\'less\', \'cssmin\', \'htmlmin\', \'imagemin\', \'jshint\', \'uglify\', \'concat\', \'qunit\'] 146 } 147 }); 148 //设置任务别名default:代表数组中的多任务,且依次执行 运行时使用grunt default(default默认不写) 149 grunt.registerTask(\'default\', [\'less\', \'cssmin\', \'htmlmin\', \'imagemin\', \'jshint\', \'uglify\', \'concat\', \'qunit\', \'watch\']); 150 };
gulp配置文件示例(gulp.js 这里使用gulp4):
1 //gulp4核心配置文件 2 var app = { // 定义目录 3 srcPath: \'src/\', 4 distPath: \'dist/\' 5 }; 6 7 /*1.引入gulp与gulp插件 使用时,要去下载这些插件*/ 8 var gulp = require(\'gulp\'); 9 var less = require(\'gulp-less\'); 10 var cssmin = require(\'gulp-cssmin\'); 11 var uglify = require(\'gulp-uglify\'); 12 var concat = require(\'gulp-concat\'); 13 var imagemin = require(\'gulp-imagemin\'); 14 var htmlmin = require(\'gulp-htmlmin\'); 15 var rename = require(\'gulp-rename\'); 16 var qunit = require(\'gulp-qunit\'); 17 /*压缩html*/ 18 function html () { 19 //配置压缩项 20 var options = { 21 removeComments: true, //清除HTML注释 22 collapseWhitespace: true, //压缩HTML 23 collapseBooleanAttributes: true, //省略布尔属性的值 <input checked="true"/> ==> <input /> 24 removeEmptyAttributes: true, //删除所有空格作属性值 <input id="" /> ==> <input /> 25 removeScriptTypeAttributes: true, //删除<script>的type="text/javascript" 26 removeStyleLinkTypeAttributes: true, //删除<style>和<link>的type="text/css" 27 minifyJS: true, //压缩页面JS 28 minifyCSS: true //压缩页面CSS 29 }; 30 /*要操作哪些文件 确定源文件地址*/ 31 gulp.src(app.srcPath + \'pages/*.html\') /*src下所有目录下的所有.html文件*/ 32 .pipe(htmlmin(options)) 33 .pipe(gulp.dest(app.distPath + \'pages\')); 34 }; 35 /*编译less生成css,压缩并合并css */ /*注意方法名不要起成less,或者cssmin,会和框架冲突 */ 36 function csstask() { 37 gulp.src(app.srcPath + \'less/*.less\') 38 .pipe(less()) 39 .pipe(gulp.dest(app.srcPath + \'css/\')) 40 /*经过压缩,放到dist目录当中*/ 41 .pipe(cssmin()) 42 .pipe(rename({ 43 extname: \'.min.css\' 44 })) 45 .pipe(gulp.dest(app.srcPath + \'css/\')) 46 .pipe(concat(\'app.css\')) 47 .pipe(gulp.dest(app.distPath + \'css\')); 48 }; 49 /*压缩并合并js*/ 50 function js() { 51 gulp.src(app.srcPath + \'js/*.js\') 52 .pipe(uglify()) 53 .pipe(rename({ 54 extname: \'.min.js\' 55 })) 56 .pipe(gulp.dest(app.srcPath + \'js/min/\')) 57 .pipe(concat(\'app.js\')) 58 .pipe(gulp.dest(app.distPath + \'js\')); 59 }; 60 /*压缩图片*/ 61 function image() { 62 gulp.src(app.srcPath + \'images/*\') 63 .pipe(imagemin()) 64 .pipe(gulp.dest(app.distPath + \'images\')); 65 }; 66 //html测试 67 function test(){ 68 gulp.src(app.distPath + \'pages/*.html\') 69 .pipe(qunit()); 70 }; 71 //当前bulid时,会自动把数组当中的所有任务给执行了。 72 // gulp.task(\'build\', [\'less\', \'html\', \'js\', \'image\', \'test\']); 73 function builder(){ 74 return gulp.series(gulp.parallel(csstask,html,js,image),test); 75 } 76 //设置监听器 77 // function watch [\'build\'], function () { 78 // /*监听哪些任务*/ 79 // // gulp.watch(\'bower_components/**/*\',[\'lib\']); 80 // gulp.watch(app.srcPath + \'/*.html\', [\'html\']); 81 // gulp.watch(app.srcPath + \'js/*.js\', [\'js\']); 82 // gulp.watch(app.srcPath + \'images/*\', [\'image\']); 83 // gulp.watch(app.srcPath + \'less/*.less\', [\'less\']); 84 // }); 85 gulp.watch(app.srcPath + \'/*.html\', html); 86 gulp.watch(app.srcPath + \'js/*.js\', js); 87 gulp.watch(app.srcPath + \'images/*\',image); 88 gulp.watch(app.srcPath + \'less/*.less\',csstask); 89 /*定义默认任务 90 * 直接执行gulp 会调用的任务 91 * */ 92 // gulp.task(\'default\', [\'watch\']); 93 exports.default=builder();
webpack配置文件示例(webpack.config.js)
1 const path = require(\'path\'); 2 const MiniCssExtractPlugin = require("mini-css-extract-plugin"); //提取成单个css文件 3 const OptimizeCssAssetsPlugin = require(\'optimize-css-assets-webpack-plugin\'); //压缩css插件 4 const HtmlWebpackPlugin = require(\'html-webpack-plugin\'); //html文件打包,压缩 5 const CleanWebpackPlugin = require("clean-webpack-plugin"); //删除原来的打包文件 6 const copyWebpackPlugin = require("copy-webpack-plugin"); //复制静态文件 7 8 module.exports = { 9 mode: \'development\', 10 entry: { //入口文件 11 index: \'./src/js/index.js\', 12 }, 13 output: { //出口文件 14 publicPath: \'\', //模板、样式、脚本、图片等资源的路径中统一会加上额外的路径 15 path: path.resolve(__dirname, \'dist\'), 16 filename: \'./js/[name].[hash:8].js\' 17 }, 18 module: { 19 rules: [ 20 { 21 test: /\.html$/, 22 use: { 23 loader: \'html-loader\', 24 options: { 25 26 } 27 } 28 }, 29 { 30 test: /\.js$/, 31 // exclude: /node_modules/, 32 exclude: path.resolve(__dirname, \'node_modules\'), //编译时,不需要编译哪些文件 33 //include: path.resolve(__dirname, \'src\'),//在config中查看 编译时,需要包含哪些文件 34 loader: \'babel-loader\', 35 query: { 36 presets: [\'latest\'] //按照最新的ES6语法规则去转换 37 } 38 }, 39 { 40 test: /\.css$/, 41 use: [ 42 // {loader: "style-loader"}, //在页面内嵌入css 43 { 44 loader: MiniCssExtractPlugin.loader, 45 options: { 46 // 这里可以指定一个 publicPath 47 // 默认使用 webpackOptions.output中的publicPath 48 publicPath: \'../\' 49 } 50 }, //单独抽离css 51 {loader: "css-loader"}, 52 { //自动添加前缀 53 loader: "postcss-loader", 54 options: { 55 plugins: [ 56 require("autoprefixer") 57 ] 58 } 59 } 60 ] 61 }, 62 { 63 test: /\.(png|jpe?g|gif|svg)(\?.*)?$/, 64 loader: \'url-loader\', 65 options: { 66 limit: 100, 67 name: \'./img/[name].[hash:7].[ext]\', 68 } 69 }, 70 ] 71 }, 72 plugins: [ 73 new CleanWebpackPlugin(), //删除上次打包文件,默认目录\'./dist\' 74 new copyWebpackPlugin([{ //静态资源输出,将src目录下的assets文件夹复制到dist目录下 75 from: path.join(__dirname, "./src/assets"), 76 to: path.join(__dirname, "./dist/assets"), 77 }]), 78 new MiniCssExtractPlugin({ 79 filename: "./css/[name].[hash:8].css" 80 }), 81 new OptimizeCssAssetsPlugin(), //压缩css文件 82 new HtmlWebpackPlugin({ 83 favicon: \'./src/img/favicon.ico\', //图标 84 template: \'./src/index.html\', //指定要打包的html 85 filename:\'index.html\', //指定输出路径和文件名 86 minify: { //压缩 87 removeComments: true, //移除HTML中的注释 88 collapseWhitespace:true, //删除空白符与换行符 89 removeAttributeQuotes: true //去除属性引用 90 } 91 }), 92 // new HtmlWebpackPlugin(//打包第二个页面 93 // { 94 // template: \'./app/src/page/index2.html\', 95 // filename:\'./page/index2.html\' 96 // } 97 // ) 98 ] 99 };
注:以上配置文件仅是简单示例,具体功能需要实际选择和配置