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 };
注:以上配置文件仅是简单示例,具体功能需要实际选择和配置