自动化构建工具(一) Grunt

一、安装node

Grunt和所有grunt插件都是基于nodejs来运行的,输入node -v来查看nodejs的版本,和试验nodejs是否安装成功。
  在这里插入图片描述

二、安装grunt-CLI

npm install -g grunt-cli

在这里插入图片描述

三、创建一个简单的网站

Grunt是应用于实际项目的,所以我们得有一个简单的测试网站来演示grunt的安装、使用。

首先,新建了一个“grunt_demo”文件夹,里面建了一个空文件夹:js,两个空文档:package.json、Gruntfile.js,名称如下图。
在这里插入图片描述

其他的东西先不要管,先把package.json这个文件写一些东西。
Package.json的内容我们写成如下格式:

{
    
    
  "name": "my-project-name",
  "version": "0.1.0",
  "devDependencies": {
    
    
    "grunt": "~0.4.5",
    "grunt-contrib-jshint": "~0.10.0",
    "grunt-contrib-nodeunit": "~0.4.1",
    "grunt-contrib-uglify": "~0.5.0"
  }
}

四、安装grunt

npm install grunt --save-dev

打开package.json去看看,那里的“devDependencies”有什么变化。

在这里插入图片描述
文档目录中的文件或者文件夹有什么变化?我这里多了一个“node_modules”文件夹,其中有一个“grunt”文件夹,再其中有若干文档。这里就是存储grunt源文件的地方。
  
在这里插入图片描述

经过以上三步,说明grunt已经在这个目录下成功安装。
在这里插入图片描述

那么,为何我们在刚才执行grunt时候会有Warning提示呢?根据提示,我们得知的信息是:Task “default” not found ,如何搞定这个问题?——当然是继续往下看啊。

五、配置Gruntfile.js

按照grunt的规定,我们首先把Gruntfile.js配置成如下格式。

module.exports = function(grunt) {
    
    

  // Project configuration.
  grunt.initConfig({
    
    
    pkg: grunt.file.readJSON('package.json'),
  	......
  });



  // 默认被执行的任务列表。
  grunt.registerTask('default', []);

};

在以上代码中,我们看到了刚才运行grunt命令,warning提示中的“default”字眼。不妨我们此时再运行一下grunt命令,看看会不会再次出现“warning”、“default”等字眼。

在这里插入图片描述

运行结果告诉我们“Done, without errors”。那就继续往下吧。

六、Grunt插件介绍

在这里插入图片描述
在这里插入图片描述

插件分为两类:
第一类是grunt团队贡献的插件,这些插件的名字前面都带有“contrib-”前缀,而且在插件列表中有星号标注。
第二类是第三方提供的插件,不带有这两个特征。

常用的插件:
grunt-contrib-clean——清除文件(打包处理生成的)
grunt-contrib-concat——合并多个文件的代码到一个文件中
grunt-contrib-uglify——压缩js文件
grunt-contrib-jshint——javascript语法错误检查;
grunt-contrib-cssmin——压缩/合并css文件
grunt-contrib-htmlmin——压缩html文件
grunt-contrib-imagemin——压缩图片文件(无损)
grunt-contrib-copy——复制文件、文件夹
grunt-contrib-watch——实时监控文件变化、调用相应的任务重新执行

七、使用uglify插件(压缩javascript代码)

在这里插入图片描述
7.1 下载模块

npm install grunt-contrib-uglify --save-dev

package.json

在这里插入图片描述

7.2 加载模块

grunt.loadNpmTasks('grunt-contrib-uglify');

7.3 demo文件结构
在这里插入图片描述
a.js

(function() {
    
    
    //output hello grunt
    var helloGrunt = "Hello Grunt!(From a.js)";
    console.log(helloGrunt);
})();

b.js

(function() {
    
    
    //output hello world
    var helloWorld = "Hello World!(From b.js)";
    console.log(helloWorld);
})();

7.4 四个任务

  • 压缩a.js,不混淆变量名,保留注释,添加banner和footer
  • 压缩b.js,输出压缩信息
  • 按原文件结构压缩js文件夹内所有JS文件
  • 合并压缩a.js和b.js

Gruntfile.js

//包装函数
module.exports = function (grunt) {
    
    

    // 任务配置,所有插件的配置信息
    grunt.initConfig({
    
    
        //获取package.json的信息
        pkg: grunt.file.readJSON('package.json'),

        uglify: {
    
    
            options: {
    
    
            	//banner在文件首行的注释说明内容
                banner: '/*! <%= pkg.name %> <%= grunt.template.today("yyyy-mm-dd") %> */\n' //注释名称
            },
            //任务1.压缩a.js,不混淆变量名,保留注释,添加banner和footer
            builda: {
    
    //任务一:压缩a.js,不混淆变量名,保留注释,添加banner和footer
                options: {
    
    
                    mangle: false, //不混淆变量名
                    preserveComments: 'all', //不删除注释,还可以为 false(删除全部注释),some(保留@preserve @license @cc_on等注释)
                    //footer在文件末行的注释说明内容
                    footer:'\n/*! <%= pkg.name %> 最后修改于: <%= grunt.template.today("yyyy-mm-dd") %> */'//添加footer
                },
                files: {
    
    
               		 //源文件和目标文件。即规定了要压缩谁?压缩之后会生成谁?
                    'output/js/a.min.js': ['js/a.js']
                }
            },
            //任务二:压缩b.js,输出压缩信息
            buildb:{
    
    
                options: {
    
    
                    report: "min"//输出压缩率,可选的值有 false(不输出信息),gzip
                },
                files: {
    
    
                    'output/js/b.min.js': ['js/main/b.js']
                }
            },
            //任务三:按原文件结构压缩js文件夹内所有JS文件
            buildall: {
    
    
                files: [{
    
    
                    expand:true,//expand:true   js css 独立 否则合并成一个
                    cwd:'js',//js目录下 //cwd :相对的根目录
                    src:'**/*.js',//所有js文件  //src:源文件
                    dest: 'output/js'//输出到此目录下 //dest:目标文件 或者文件夹(根据expand 是否为true 判断)
                }]
            },
            //任务四:合并压缩a.js和b.js
            release: {
    
    
                files: {
    
    
                    'output/js/index.min.js': ['js/a.js', 'js/main/b.js']
                }
            }

        }
       



    });

    
    //加载grunt-contrib-uglify模块
     grunt.loadNpmTasks('grunt-contrib-uglify');

   //将uglify任务注册到默认指令中
    // grunt.registerTask('builda', ['uglify:build_a']);
    // 默认任务
    grunt.registerTask('default', ['uglify:release']);
    grunt.registerTask('mina', ['uglify:builda']);
    grunt.registerTask('minb', ['uglify:buildb']);
    grunt.registerTask('minall', ['uglify:buildall']);

};

7.5 运行结果

7.5.1 压缩a.js,不混淆变量名,保留注释,添加banner和footer

运行 grunt mina 命令,生成的a.min.js如下:
在这里插入图片描述
在这里插入图片描述
7.5.2 压缩b.js,输出压缩信息

运行 grunt minb 命令,生成的b.min.js如下:
在这里插入图片描述
在这里插入图片描述
7.5.3 按原文件结构压缩js文件夹内所有JS文件

运行 grunt minall 命令,生成目录结构如下:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
7.5.4 合并压缩a.js和b.js

运行 grunt命令,生成的output/index.min.js内容如下:
在这里插入图片描述
在这里插入图片描述

八、 使用concat插件 (合并js)

8.1 下载模块

npm install grunt-contrib-concat --save-dev

在这里插入图片描述

8.2 加载模块

grunt.loadNpmTasks('grunt-contrib-concat');

8.3 配置任务

//包装函数
module.exports = function (grunt) {
    
    

    // 任务配置,所有插件的配置信息
    grunt.initConfig({
    
    
        //获取package.json的信息
        pkg: grunt.file.readJSON('package.json'),

        //合并js
        concat: {
    
    
            options: {
    
     //可选项配置
                separator: ';' //使用;连接合并
            },
            js: {
    
    //此名称任意
                src: ['concat/js/*.js'],//合并哪些js文件
                dest: 'concat/build/all.js'//输出的js文件
            },
            css: {
    
    
                src: ['concat/css/*.css'],
                dest: 'concat/build/all.css'
            }
        }




    });


    //加载插件
    grunt.loadNpmTasks('grunt-contrib-concat');
    //注册任务
    grunt.registerTask('concat-js', ['concat:js']);//单独执行js合并
    grunt.registerTask('concat-css', ['concat:css']);//单独执行css合并

};

8.4 demo文件结构
在这里插入图片描述

8.4 运行结果

8.4.1 运行grunt concat-js:只合并js文件
在这里插入图片描述

在这里插入图片描述

8.4.2 运行 grunt concat-css:只合并css文件
在这里插入图片描述

在这里插入图片描述

九、使用jshint插件 (js语法检查)

9.1 下载模块

npm install grunt-contrib-jshint --save-dev

在这里插入图片描述

9.2 加载模块

grunt.loadNpmTasks('grunt-contrib-jshint');

9.3 配置任务

//包装函数
module.exports = function (grunt) {
    
    

    // 任务配置,所有插件的配置信息
    grunt.initConfig({
    
    
        //获取package.json的信息
        pkg: grunt.file.readJSON('package.json'),

        //js语法检查
        jshint: {
    
    
            options: {
    
    
                //大括号包裹
                curly: true,
                //对于简单类型,用于===和!==,而不是==和!=
                eqeqeq: true,
                //对于首字母大写的函数(声明的类),强制使用new
                newcap: true,
                //禁用arguments.caller和arguments.callee
                noarg: true,
                // 对于属性使用aaa.bbb,而不是aaa['bbb']
                sub: true,
                //查找所有未定义变量
                undef: true,
                //查找类似与if(a = 0)这样的代码
                boss: true,
                //指定运行环境为node.js
                node: true
            },
            //具体任务配置
            all: ['Gruntfile.js', 'app/**/*.js', 'js/**/*.js'],
            files: {
    
    
                src: ['app/**/*.js']
            }

        },

    });

 	//加载插件
    grunt.loadNpmTasks('grunt-contrib-jshint');

	//注册任务
    grunt.registerTask('jshint-all', ['jshint:all']);
    grunt.registerTask('jshint-files', ['jshint:files']);
   
};

9.4 运行结果
在这里插入图片描述

十、使用watch插件(真正实现自动化)

实时监控文件变化、调用相应的任务重新执行

10.1 下载模块

npm install grunt-contrib-watch --save-dev

10.2 加载模块

grunt.loadNpmTasks('grunt-contrib-watch');

10.3 配置任务

//包装函数
module.exports = function (grunt) {
    
    

    // 任务配置,所有插件的配置信息
    grunt.initConfig({
    
    
        //获取package.json的信息
        pkg: grunt.file.readJSON('package.json'),

        //压缩js文件
        uglify: {
    
    
            options: {
    
    
                //banner在文件首行的注释说明内容
                banner: '/*! <%= pkg.name %> <%= grunt.template.today("yyyy-mm-dd") %> */\n' //注释名称
            },
            //任务1.压缩a.js,不混淆变量名,保留注释,添加banner和footer
            builda: {
    
     //任务一:压缩a.js,不混淆变量名,保留注释,添加banner和footer
                options: {
    
    
                    mangle: false, //不混淆变量名
                    preserveComments: 'all', //不删除注释,还可以为 false(删除全部注释),some(保留@preserve @license @cc_on等注释)
                    //footer在文件末行的注释说明内容
                    footer: '\n/*! <%= pkg.name %> 最后修改于: <%= grunt.template.today("yyyy-mm-dd") %> */' //添加footer
                },
                files: {
    
    
                    //源文件和目标文件。即规定了要压缩谁?压缩之后会生成谁?
                    'output/js/a.min.js': ['js/a.js']
                }
            },
            //任务二:压缩b.js,输出压缩信息
            buildb: {
    
    
                options: {
    
    
                    report: "min" //输出压缩率,可选的值有 false(不输出信息),gzip
                },
                files: {
    
    
                    'output/js/b.min.js': ['js/main/b.js']
                }
            },
            //任务三:按原文件结构压缩js文件夹内所有JS文件
            buildall: {
    
    
                files: [{
    
    
                    expand: true, //expand:true   js css 独立 否则合并成一个
                    cwd: 'js', //js目录下 //cwd :相对的根目录
                    src: '**/*.js', //所有js文件  //src:源文件
                    dest: 'output/js' //输出到此目录下 //dest:目标文件 或者文件夹(根据expand 是否为true 判断)
                }]
            },
            //任务四:合并压缩a.js和b.js
            release: {
    
    
                files: {
    
    
                    'output/js/index.min.js': ['js/a.js', 'js/main/b.js']
                }
            }

        },

        //合并js
        concat: {
    
    
            options: {
    
     //可选项配置
                separator: ';' //使用;连接合并
            },
            js: {
    
     //此名称任意
                src: ['concat/js/*.js'], //合并哪些js文件
                dest: 'concat/build/all.js' //输出的js文件
            },
            css: {
    
    
                src: ['concat/css/*.css'],
                dest: 'concat/build/all.css'
            }
        },

        //js语法检查
        jshint: {
    
    
            options: {
    
    
                //大括号包裹
                curly: true,
                //对于简单类型,用于===!==,而不是==!=
                eqeqeq: true,
                //对于首字母大写的函数(声明的类),强制使用new
                newcap: true,
                //禁用arguments.caller和arguments.callee
                noarg: true,
                // 对于属性使用aaa.bbb,而不是aaa['bbb']
                sub: true,
                //查找所有未定义变量
                undef: true,
                //查找类似与if(a = 0)这样的代码
                boss: true,
                //指定运行环境为node.js
                node: true
            },
            //具体任务配置
            all: ['Gruntfile.js', 'app/**/*.js', 'js/**/*.js'],
            files: {
    
    
                src: ['app/**/*.js']
            }

        },

        //实时监控文件变化、调用相应的任务重新执行
        watch : {
    
    
            scripts : {
    
    
              files : ['src/js/*.js', 'src/css/*.css'],
              tasks : ['concat', 'jshint', 'uglify'],
              options : {
    
    spawn : false}  
            }
          }

    });


    //加载grunt-contrib-uglify模块
    grunt.loadNpmTasks('grunt-contrib-uglify');
    //将uglify任务注册到默认指令中
    // grunt.registerTask('default', ['uglify:release']);
    grunt.registerTask('mina', ['uglify:builda']);
    grunt.registerTask('minb', ['uglify:buildb']);
    grunt.registerTask('minall', ['uglify:buildall']);


    //加载插件
    grunt.loadNpmTasks('grunt-contrib-concat');
    //注册任务
    // grunt.registerTask('default', ['concat:concat']);
    grunt.registerTask('concat-js', ['concat:js']); //单独执行js合并
    grunt.registerTask('concat-css', ['concat:css']); //单独执行css合并


    //加载插件
    grunt.loadNpmTasks('grunt-contrib-jshint');
    //注册任务
    grunt.registerTask('jshint-all', ['jshint:all']);
    grunt.registerTask('jshint-files', ['jshint:files']);
    


    //加载插件
    grunt.loadNpmTasks('grunt-contrib-watch');
    //注册任务
    //grunt.registerTask('default', ['concat', 'uglify', 'jshint', 'watch']);
    grunt.registerTask('myWatch', ['default','watch']);


};

10.4 结果

grunt   //控制台提示watch已经开始监听, 修改保存后自动编译处理

猜你喜欢

转载自blog.csdn.net/weixin_42580704/article/details/108360316