天天看点

grunt入门grunt简介grunt使用前置准备package.json写法Gruntfile写法jshint语法检查

最近开始整理grunt相关知识,本文主要是作为指引文档,具体操作均引用其他文章。文中如有引用之处会注明。

grunt简介

grunt是什么?

  Grunt 是一个基于任务的JavaScript工程命令行构建工具。

为什么要使用grunt?

  一句话:自动化。对于需要反复重复的任务,例如压缩(minification)、编译、单元测试、linting等,自动化工具可以减轻你的劳动,简化你的工作。当你在 Gruntfile 文件正确配置好了任务,任务运行器就会自动帮你或你的小组完成大部分无聊的工作。

grunt使用前置准备

  Grunt和 Grunt 插件是通过 npm 安装并管理的,npm是 Node.js 的包管理器,所以你需要先下载node.js。传送门

npm install -g grunt 
           

  这一步也可以省略,如省略需要在package.json中写明此依赖,下面会涉及到。

  为了在命令行中使用grunt,你需要安装Grunt命令行(CLI)。

-g表示全局安装,部分系统需要sudo权限。

  每次运行grunt 时,他就利用node提供的require()系统查找本地安装的 Grunt。正是由于这一机制,你可以在项目的任意子目录中运行grunt 。如果找到一份本地安装的 Grunt,CLI就将其加载,并传递Gruntfile中的配置信息,然后执行你所指定的任务。

  使用grunt时,一般需要在你的项目中添加两份文件:package.json 和 Gruntfile。

package.json写法

  用过node的人都知道项目根目录有个package.json文件,来描述项目基本信息(作者,项目名称,版本号等)和项目需要的各种模块。

  使用grunt前需要将grunt和相关的插件安装到项目目录中,在根目录中写好package.json,将grunt和相关插件写在devDependencies一项中,并执行安装:

  没错,不指定npm安装的模块时,npm会自动搜索本目录的package.json,然后自动安装里面的devDependencies和dependencies里注明的模块。

  这一点阮一峰菊苣已经写的很详细了,不班门弄斧了。传送门

注意: 运行项目前需要到根目录执行

npm install

,要不然项目运行时会报错

Gruntfile写法

可参考http://www.hulufei.com/post/grunt-introduction

  此文件被命名为 Gruntfile.js 或 Gruntfile.coffee,用来配置或定义任务(task)并加载Grunt插件的。 此文档中提到的 Gruntfile 其实说的是一个文件,文件名是 Gruntfile.js 或 Gruntfile.coffee。

  grunt执行时会寻找项目里的Gruntfile文件。关于Gruntfile文件的命名,据实测和大小写关系不大,gruntfile, Gruntfile, GruntFile都是可以的,但按官网上的写法是Gruntfile。

Gruntfile由以下几部分构成:

  • “wrapper” 函数
  • 项目与任务配置
  • 加载grunt插件和任务
  • 自定义任务

比较常用的插件有:

  • jshint:简单的js语法检查,具体配置后面会讲到
  • uglify:压缩代码,网站优化方案之一
  • concat:代码合并,网站优化方案之一
  • watch:实时监控,当代码发生变动时自动重新编译,再也不用经常保存再刷新页面了

示例:

module.exports = function(grunt) {

    // load tasks
    [
        'grunt-contrib-jshint',
        'grunt-contrib-qunit',
        'grunt-contrib-watch',
        'grunt-contrib-clean',
        'grunt-contrib-copy',
        'grunt-contrib-concat',
        'grunt-contrib-uglify',
        'grunt-contrib-cssmin',
        'grunt-contrib-concat',
        'grunt-contrib-less',
        'grunt-contrib-coffee',
        'grunt-usemin',
        'grunt-filerev'
    ].forEach(function(task) { grunt.loadNpmTasks(task); });


    // setup init config
    grunt.initConfig({
        pkg: grunt.file.readJSON('package.json'),

        // clean up the `dist/` directory, i.e., delete files
        clean: {
            dist: {
                src: [
                    'dist/*',

                    // funny dance to keep old versioned dist/css/*.pkg.*.css
                    '!dist/css/**',
                    'dist/css/*',
                    '!dist/css/*.pkg.*.css',

                    // funny dance to keep old versioned dist/css/*.pkg.*.js
                    '!dist/js/**',
                    'dist/js/*',
                    '!dist/js/*.pkg.*.js'
                ]
            }
        },

        // copy over `src/` files to `dist/`
        copy: {
            dist: {
                files: [{
                    expand: true,
                    dot: true,
                    cwd: 'src/',
                    dest: 'dist/',
                    src: [
                        '*',
                        'css/**',
                        'js/**',
                        'ico/**',
                        'img/**'
                    ],
                    filter: 'isFile'
                }]
            }
        },

        // compile LESS files in `src/less/` into CSS files
        less: {
            css: {
                options: {
                    paths: ["src/less"]
                },
                files: [
                    {
                        expand: true,
                        cwd: 'src/less',
                        src: ['*.less'],
                        dest: 'src/css/',
                        ext: '.css'
                    }
                ]
            }
        },

        // compile coffeescript files in `/src/coffee/` into JS files
        coffee: {
            glob_to_multiple: {
                expand: true,
                // flatten: true,
                cwd: 'src/coffee',
                src: ['**/*.coffee'],
                dest: 'src/js',
                ext: '.js'
            }
        },

        // prep call for usemin (target all html files)
        useminPrepare: {
            html: [
                'dist/*.html'
            ]
        },

        // final call for usemin (target all html files)
        usemin: {
            html: [
                'dist/*.html'
            ],
            options: {
                dirs: ['dist/']
            }
        },

        // revision a specific set of static files, this can be
        // extended to do more files and images too
        filerev: {
            files: {
                src: [
                    'dist/css/*.pkg.css',
                    'dist/js/*.pkg.js'
                ]
            }
        },

        // TODO - support qunit
        qunit: {
            files: ['test/**/*.html']
        },

        // validate JS files using jshint (great for catching simple bugs)
        jshint: {
            files: ['gruntfile.js', 'src/**/*.js', 'test/**/*.js'],
            options: {
                // options here to override JSHint defaults
                globals: {
                    jQuery: true,
                    console: true,
                    module: true,
                    document: true
                },
                ignores: [
                    // enter paths to ignore here, e.g., 'src/js/jquery.js'
                ]
            }
        },

        // watch command to auto-compile files that have changed
        watch: {
            coffee: {
                files: ['src/**/*.coffee'],
                tasks: ['coffee', 'jshint']
            },
            less: {
                files: ['src/**/*.less'],
                tasks: ['less']
            }
        }
    });

    // Composite tasks...

    // run tests
    grunt.registerTask('test', ['jshint', 'qunit']);

    // like watch, but build stuff at start too!
    grunt.registerTask('dev', ['less', 'coffee', 'watch']);

    // full build of project to `dist/`
    grunt.registerTask('default', ['less', 'coffee', 'jshint', 'clean', 'copy',
                                   'useminPrepare',
                                   'concat', 'uglify', 'cssmin',
                                   'filerev',
                                   'usemin']);
};
           

  每个任务需要添加registerTask,registerTask函数第一个参数是任务名,第二个参数是执行的子任务,依次执行。

  具体写法看官网文档会比较好一些。传送门

jshint语法检查

笔者写代码的时候,由于遵循的风格和jshint的默认规则不符,各种报错,让我很是不爽。工具变成绊脚石,也是挺痛苦的。所以,需要根据个人习惯去配置一下jshint,减少不必要的报错。

推荐一篇博文:JSHint 使用说明

在grunt中使用时,将文中的选项作为Gruntfile中jshint.options的key值,配置作为value就好。例如:

module.exports = function(grunt) {

  grunt.initConfig({
    pkg: grunt.file.readJSON('package.json'),
    jshint: {
      files: ['Gruntfile.js'],
      options: {
        //这里是覆盖JSHint默认配置的选项
        globals: {
          jQuery: true,
          console: true,
          module: true,
          document: true
        },
        asi: true,
        eqeqeq: false
      }
    }
  });

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

继续阅读