# grunt 入门

# 需要做的

确保当前 node 环境及 npm 版本, 安装 grunt-cli。

npm i -g grunt-cli
  • 创建 package.json ,根据需要安装插件
// 已安装 grunt-init
grunt-init
// 未安装
npm init
npm install grunt --save-dev
npm install grunt-contrib-jshint --save-dev
npm install grunt-contrib-nodeunit --save-dev
npm install grunt-contrib-uglify --save-dev
  • 创建 Gruntfile.js / Gruntfile.coffee
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']);

};

自定义任务

grunt.registerTask('default', 'Log some stuff.', function() {
      grunt.log.write('Logging some stuff...').ok();
    }, ['uglify']);

TIP

由于 vue 源码最初使用了 grunt ,大概了解了 grunt 的基础使用, 并没有仔细看文档,所以对于一些 targets 比较疑惑。 需要注意的是,在任务中经常会看见一些 targets ,这些 target 既不是 grunt 定义的也不是插件定义的,而是自定义任务,当执行的时候会像 这样: browserify:vender 。每个 target 会拥有 files 的配置,比如 src 和 dest ,以及插件的配置。这个问题的答案是我无意中在 stakoverflow 中查到的。 https://stackoverflow.com/questions/27712941/using-grunt-browserify-in-gruntfile-js。

# 原理

grunt-cli 是一个脚手架,他可以将 grunt 配置到全局环境变量中,然后依赖于 nodejs 的 require 方式找到不同目录下的 grunt 执行, 达到可以在同一台机器上运行不同版本 grunt 的目的。

Gruntfile.js 应该在根目录并且和 package.json 同一层级,package.json 的项目元数据 (metadata) 会导入到 grunt 配置中。 通过 grunt.loadNpmTasks 加载插件,很多常用任务封装成为插件,通过配置 grunt.initConfig 使用,通过 grunt.registerTask 执行。

# 压缩代码

安装插件 npm install grunt-contrib-uglify -D。 加入代码:

// 配置插件
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'
        }
      }
    });
// 加载插件
grunt.loadNpmTasks('grunt-contrib-uglify');
// 执行任务
grunt.registerTask('default', ['uglify']);

# jshint 检查

创建 .jshintrc 配置文件, 安装插件 npm install grunt-contrib-jshint -D

module.exports = function(grunt) {
    grunt.initConfig({
      jshint: {
        src: ['src/**/*.js'],
        options: {
          jshintrc: "./.jshintrc"
        }
      }
    });
    
    grunt.loadNpmTasks( 'grunt-contrib-jshint' );
    // 默认被执行的任务列表。
    grunt.registerTask('default', ['jshint']);
  
  };

# 文件热更新

安装插件 npm install grunt-contrib-watch -Dgrunt-contrib-watch 插件可以监听文件的变更,从而触发执行其他任务。

// 监听文件变更,触发 jshint 任务:
module.exports = function(grunt) {
    // Project configuration.
    grunt.initConfig({
      jshint: {
        src: ['src/**/*.js'],
        options: {
          jshintrc: "./.jshintrc"
        }
      },
      watch: {
        files: ['src/**/*.js',],
        tasks: ['jshint']
      }
    });
    grunt.loadNpmTasks('grunt-contrib-watch');
    grunt.loadNpmTasks( 'grunt-contrib-jshint' );
    // 默认被执行的任务列表。
    grunt.registerTask('default',['jshint']);
  
  };

# 测试

可以通过两种方式执行测试脚本 grunt test

module.exports = function(grunt) {
    // Project configuration.
    grunt.initConfig({
      mocha: {
        test: {
          src: ['tests/**/*.html'],
          options: {
            run: true,
          },
        },
      },
    });
    grunt.loadNpmTasks( 'grunt-mocha' );
    // 默认被执行的任务列表。
    grunt.registerTask('test',['mocha']);
  };

也可以在页面直接运行:

<!DOCTYPE html>
<html>
  <head>
    <title>Getting Started with Component</title>
    <link rel="stylesheet" type="text/css" href="../node_modules/grunt-mocha/node_modules/mocha/mocha.css">
  </head>
  <body>
    <div id="mocha"></div>
    <script src="../node_modules/grunt-mocha/node_modules/mocha/mocha.js"></script>
    <script type="text/javascript" charset="utf-8">
    // Only tests run in real browser, injected script run if options.run == true
    if (navigator.userAgent.indexOf('PhantomJS') < 0) {
      mocha.run();
    }
  </script> 
  </body>
</html>

WARNING

grunt-mocha 使用 PhantomJS 运行 html ,而今天 PhantomJS 已经不再适用了。

# 模块打包器 grunt-browserify

module.exports = function(grunt) {
    // Project configuration.
    grunt.initConfig({
      browserify: {
        build: {
          src: ['src/main.js'],
          dest: 'build/bundle.js',
          options: {
            browserifyOptions: {
              standalone: 'Seed' // name for use module on browser
            }
          }
        }
      }
  });
    grunt.loadNpmTasks('grunt-browserify');
    // 默认被执行的任务列表。
    grunt.registerTask('default',['browserify']);
  };

# 补充

grunt 可以创建自定义任务来执行。

grunt.registerTask('all',['jshint']);

对于多文件任务,可以采取:

build: {
  files:[{
    src:[],
    dest:''
  }]
}