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 };
注:以上配置文件僅是簡單示例,具體功能需要實際選擇和配置