grunt学习笔记

227 阅读3分钟
前言

grunt官网称之为JavaScript世界的构建工具,一个基于nodeJs的前端自动化工具,可以用来处理一些反复重复的任务,比如压缩、编译、单元测试等。

基础

使用grunt需要安装gruntgrunt-cli

一般在根目录下新建一个Gruntfile.js来当作grunt的配置文件,其主要有四部分组成:

以官网中的这个例子来说:

module.exports = function(grunt) {

  // Project configuration.
  grunt.initConfig({
    pkg: grunt.file.readJSON('package.json'),
    uglify: {
      options: {
        banner: '/*! <%= pkg.name %> <%= grunt.template.today("yyyy-mm-dd") %> */\n'
      },
      build: {
        src: 'src/<%= pkg.name %>.js',
        dest: 'build/<%= pkg.name %>.min.js'
      }
    }
  });

  // 加载包含 "uglify" 任务的插件。
  grunt.loadNpmTasks('grunt-contrib-uglify');

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

};
  • 包装函数wrapper

    配置文件都会由一个模块来包裹着:

    module.exports = function(grunt) {
      // Do grunt-related things in here
    };
    
  • 项目与任务配置

    grunt的任务都需要依赖定义在grunt.initConfig的配置方法。详细可以看下npm文档

    这里在grunt.initConfig中配置了一个uglify,配置了banner和build,banner设置头部输出信息,主要通过设置一个字符串,此字符串将被添加到缩小输出之前。模板字符串(例如 <%= config.value %>)将自动展开;build来设置压缩的入口和出口。

  • 加载grunt插件

      // 加载包含 "uglify" 任务的插件。
      grunt.loadNpmTasks('grunt-contrib-uglify');
    
  • 注册任务

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

    注册任务就是根据我们在grunt.initConfig中的配置来调用插件函数,或者自定义任务:

    grunt.registerTask('markDev', ['concat', 'cssmin:cssPart']);
    

    在命令行调用grunt markDev即可。

实例

接下来我们用一个例子更加深入的理解下上述概念。

首先npm init -y初始化一个包,安装如下依赖:

"devDependencies": {
  "grunt": "~0.4.2",
  "grunt-contrib-jshint": "~0.6.0",
  "grunt-contrib-nodeunit": "~0.2.0",
  "grunt-contrib-uglify": "~0.2.2"
},

在根目录下新建js/a.jsjs/main/b.js,分别写上:

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

再新建配置文件Gruntfile.js

module.exports = function(grunt){

    grunt.initConfig({
        pkg: grunt.file.readJSON('package.json'),
        uglify: {
            options: {
                banner: '/*! <%= pkg.name %> <%= grunt.template.today("yyyy-mm-dd") %> */\n'//添加banner
            },
            builda: {
                options: {
                    mangle: false, //不混淆变量名
                    preserveComments: 'all', //不删除注释,还可以为 false(删除全部注释),some(保留@preserve @license @cc_on等注释)
                    footer:'\n/*! <%= pkg.name %> 最后修改于: <%= grunt.template.today("yyyy-mm-dd") %> */'//添加footer
                },
                files: {
                    'output/js/a.min.js': ['js/a.js']
                }
            },
        }
    });

    // 加载提供"uglify"任务的插件
    grunt.loadNpmTasks('grunt-contrib-uglify');
	//注册任务
    grunt.registerTask('nicka', ['uglify:builda']);
}

initConfig中首先读取package.sjon,再设置执行grunt-contrib-uglify插件的配置uglify,首先在options中添加注释,注释内容为当前包的名称和当前时间;在builda中分别设置manglepreserveComments,不混淆变量名和不删除注释,再添加一个尾部注释,最后在files中设置入口文件和出口文件: 'output/js/a.min.js': ['js/a.js']

运行grunt nicka,既可以看到在根目录下有一个output/js/a.min.js:

/*! grunttext 2022-03-23 */
!function(){
//output hello grunt
var helloGrunt="Hello Grunt!(From a.js)";console.log(helloGrunt)}();
/*! grunttext 最后修改于: 2022-03-23 */

如果想将a.jsb.js合并压缩,可以在initConfig中添加release配置:

release: {
    files: {
        'output/js/index.min.js': ['js/a.js', 'js/main/b.js']
    }
}

//注册任务
grunt.registerTask('default', ['uglify:release']);

运行grunt,可以看到压缩后的文件:

//  index.min.js
/*! grunttext 2022-03-23 */
!function(){var a="Hello Grunt!(From a.js)";console.log(a)}(),function(){var a="Hello World!(From b.js)";console.log(a)}();

在该目录下运行:node index.min.js

Hello Grunt!(From a.js)
Hello World!(From b.js)

看到打印的输出内容,表明压缩没问题。

代码地址