搜索
首页web前端js教程什么是Grunt?对他的详细介绍

前面的话

  前端技术的发展真的很快,15年还在流行grunt,而现在随着gulp的大量使用,以及webpack越来越流行,grunt基本上要被淘汰了。学习进度跟不上技术发展进度,实在是说不出的感觉。本文将介绍可能将过时的grunt

安装

  Grunt和Grunt插件是通过npm安装并管理的。在学习Grunt前,需要先将Grunt命令行(CLI)安装到全局环境中。安装时可能需要使用sudo(针对OSX、*nix、BSD等系统中)权限或者作为管理员(对于Windows环境)来执行以下命令

npm install -g grunt-cli

  上述命令执行完后,grunt命令就被加入到系统路径中了,以后就可以在任何目录下执行此命令了

  [注意]安装grunt-cli并不等于安装了Grunt。Grunt CLI的任务很简单:调用与Gruntfile在同一目录中的Grunt。这样带来的好处是,允许在同一个系统上同时安装多个版本的Grunt

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

 

配套

  一般需要在项目中添加两份文件:package.json 和 Gruntfile

  package.json: 此文件被npm用于存储项目的元数据,以便将此项目发布为npm模块。可以在此文件中列出项目依赖的grunt和Grunt插件,放置于devDependencies配置段内

  Gruntfile: 此文件被命名为 Gruntfile.js 或 Gruntfile.coffee,用来配置或定义任务(task)并加载Grunt插件

【package.json】

  package.json应当放置于项目的根目录中,与Gruntfile在同一目录中,并且应该与项目的源代码一起被提交。在上述目录(package.json所在目录)中运行npm install将依据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"
  }
}

  向已经存在的package.json 文件中添加Grunt和grunt插件的最简单方式是通过npm install <module> --save-dev命令。此命令不光安装了<module>,还会自动将其添加到devDependencies 配置段中,如下所示

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

【Gruntfile】

  Gruntfile.js 或 Gruntfile.coffee 文件是有效的 JavaScript 或 CoffeeScript 文件,应当放在项目根目录中,和package.json文件在同一目录层级,并和项目源码一起加入源码管理器

  Gruntfile由以下几部分构成:

  • "wrapper" 函数

  • 项目与任务配置

  • 加载grunt插件和任务

  • 自定义任务

  在下面列出的这个 Gruntfile 中,package.json文件中的项目元数据(metadata)被导入到 Grunt 配置中, grunt-contrib-uglify 插件中的uglify 任务(task)被配置为压缩(minify)源码文件并依据上述元数据动态生成一个文件头注释。当在命令行中执行 grunt 命令时,uglify 任务将被默认执行

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']);

};

  1、wrapper函数

  每一份 Gruntfile (和grunt插件)都遵循同样的格式,所书写的Grunt代码必须放在wrapper函数内

module.exports = function(grunt) {  // Do grunt-related things in here};

  2、项目和任务配置

  大部分的Grunt任务都依赖某些配置数据,这些数据被定义在一个object内,并传递给grunt.initConfig 方法

  Grunt的task配置都是在 Gruntfile 中的grunt.initConfig方法中指定的。此配置主要是以任务名称命名的属性,也可以包含其他任意数据。一旦这些代表任意数据的属性与任务所需要的属性相冲突,就将被忽略

grunt.initConfig({
  concat: {// 这里是concat任务的配置信息。  },
  uglify: {// 这里是uglify任务的配置信息  },  // 任意数据。
  my_property: 'whatever',
  my_src_files: ['foo/*.js', 'bar/*.js'],
});

  在一个任务配置中,options属性可以用来指定覆盖内置属性的默认值。此外,每一个目标(target)中还可以拥有一个专门针对此目标(target)的options属性。目标(target)级的平options将会覆盖任务级的options。options对象是可选的,如果不需要,可以忽略

grunt.initConfig({
  concat: {
    options: {      // 这里是任务级的Options,覆盖默认值     },
    foo: {
      options: {// "foo" target options may go here, overriding task-level options.      },
    },
    bar: {      // No options specified; this target will use task-level options.    },
  },
});

  在下面的案例中,grunt.file.readJSON('package.json') 将存储在package.json文件中的JSON元数据引入到grunt config中。 由于<% %>模板字符串可以引用任意的配置属性,因此可以通过这种方式来指定诸如文件路径和文件列表类型的配置数据,从而减少一些重复的工作

  与大多数task一样,grunt-contrib-uglify插件中的uglify 任务要求它的配置被指定在一个同名属性中。在这里有一个例子, 我们指定了一个banner选项(用于在文件顶部生成一个注释),紧接着是一个单一的名为build的uglify目标,用于将一个js文件压缩为一个目标文件

// 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'}
  }
});

  3、加载grunt插件和任务

  像 concatenation、[minification]、grunt-contrib-uglify 和 linting这些常用的任务(task)都已经以grunt插件的形式被开发出来了。只要在 package.json 文件中被列为dependency(依赖)的包,并通过npm install安装之后,都可以在Gruntfile中以简单命令的形式使用:

// 加载能够提供"uglify"任务的插件。grunt.loadNpmTasks('grunt-contrib-uglify');

  [注意] grunt --help 命令将列出所有可用的任务

  4、自定义任务

  通过定义 default 任务,可以让Grunt默认执行一个或多个任务。在下面的这个案例中,执行 grunt 命令时如果不指定一个任务的话,将会执行uglify任务。这和执行grunt uglify 或者 grunt default的效果一样。default任务列表数组中可以指定任意数目的任务(可以带参数)

// Default task(s).grunt.registerTask('default', ['uglify']);

 

合并

  本节将介绍合并插件grunt-contrib-concat的实例应用

  1、首先,建立项目结构。 根目录为'project',存在一个'src'的文件夹,该文件夹下又包含'css'和'js'这两个文件夹。其中,'css'文件夹有一个空的'concat'文件夹,一个'style1.css'文件,以及一个'style2.css'文件;类似地,'js'文件夹有一个空的'concat'文件夹,一个'script1.js'文件,以及一个'script2.js'文件

  由于需要用到grunt来实现合并,所以需要在项目根目录下,新建'package.json'和'Gruntfile.js'文件

  最终的目录结构如下所示

  2、填充文件内容

  合并的目的是把'style1.css'和'style2.css'的内容合并到'css/src/concat'文件夹下,把'script1.js'和'script2.js'的内容合并到'js/src/concat'文件夹下

  style1.css的文件内容如下

body{margin: 0;}

  style2.css的文件内容如下

ul{margin: 0;padding: 0;list-style:none;
}

  script1.js的文件内容如下

console.log('a');

  script2.js的文件内容如下

console.log('b');

  3、设置Grunt的package.json及Gruntfile.js文件

  由于需要用到grunt及grunt-contrib-concat插件,所以package.json的文件内容如下

{  "name": "project",  "version": "1.0.0",  "devDependencies": {"grunt": "^1.0.1","grunt-contrib-concat": "^1.0.1"
  }
}

  Gruntfile.js的配置文件如下

module.exports = function(grunt) {
  grunt.initConfig({
    pkg: grunt.file.readJSON('package.json'),
    concat: {
      options: {stripBanners: true,
        banner: '/*! <%= pkg.name %> - v<%= pkg.version %> - ' +'<%= grunt.template.today("yyyy-mm-dd") %> */'  },
      myCSSDist: {
        src: ['src/css/*.css'],
        dest: 'src/css/concat/<%= pkg.name %>-<%= pkg.version %>.css'  },
      myJSDist: {
        src: ['src/js/*.js'],
        dest: 'src/js/concat/<%= pkg.name %>-<%= pkg.version %>.js'  },      
    },
  });
  grunt.loadNpmTasks('grunt-contrib-concat');
  grunt.registerTask('default', ['concat']);
};

  4、效果演示

  通过在命令行中使用npm install命令来安装插件

npm install

  然后执行命令grunt

  在'css/concat'文件夹下生成一个'project-1.0.0.css'的文件,内容如下

body{margin: 000-

  在'js/concat'文件夹下生成一个'project-1.0.0.js'的文件,内容如下

/*! project - v1.0.0 - 2017-05-27 */console.log('a');console.log('b');

 

压缩

  接下来,我们对合并后的project-1.0.0.css和project-1.0.0.js文件进行压缩,压缩名称加一个'.min'前缀,并分别保存到'project'目录下的'dist'目录下'css'文件夹和'js'文件夹

  由于需要用到grunt-contrib-cssmin和grunt-contrib-uglify插件,所以package.json的文件内容如下

{  "name": "project",  "version": "1.0.0",  "devDependencies": {"grunt": "^1.0.1","grunt-contrib-concat": "^1.0.1","grunt-contrib-cssmin": "^2.2.0","grunt-contrib-uglify": "^3.0.1"
  }
}

  Gruntfile.js的配置文件如下

module.exports = function(grunt) {
  grunt.initConfig({
    pkg: grunt.file.readJSON('package.json'),
    concat: {
      options: {
        stripBanners: true,
        banner: '/*! <%= pkg.name %> - v<%= pkg.version %> - ' +'<%= grunt.template.today("yyyy-mm-dd") %> */'  },
      myCSSDist: {
        src: ['src/css/*.css'],
        dest: 'src/css/concat/<%= pkg.name %>-<%= pkg.version %>.css'  },
      myJSDist: {
        src: ['src/js/*.js'],
        dest: 'src/js/concat/<%= pkg.name %>-<%= pkg.version %>.js'  },      
    },
    cssmin:{
      options: {
        stripBanners: true,
        banner: '/* <%= grunt.template.today("yyyy-mm-dd") %> */'        
      },
      build:{
        src: 'src/css/concat/<%= pkg.name %>-<%= pkg.version %>.css',
        dest: 'dist/css/<%= pkg.name %>-<%= pkg.version %>.min.css'        
      }

    },
    uglify:{
      options: {
        stripBanners: true,
        banner: '/* <%= grunt.template.today("yyyy-mm-dd") %> */'        
      },
      build:{
        src: 'src/js/concat/<%= pkg.name %>-<%= pkg.version %>.js',
        dest: 'dist/js/<%= pkg.name %>-<%= pkg.version %>.min.js'        
      }
    }
  });
  grunt.loadNpmTasks('grunt-contrib-concat');
  grunt.loadNpmTasks('grunt-contrib-cssmin');
  grunt.loadNpmTasks('grunt-contrib-uglify');
  grunt.registerTask('default', ['concat','cssmin','uglify']);
};

  通过在命令行中使用npm install命令来安装插件

  然后执行命令grunt

  在'dist/css/'文件夹下生成一个'project-1.0.0.min.css'的文件,内容如下

/*! project - v1.0.0 - 2017-05-27 */body{margin:0}ul{margin:0;padding:0;list-style:none}

  在'dist/js/'文件夹下生成一个'project-1.0.0.min.js'的文件,内容如下

/* 2017-05-27 */console.log("a"),console.log("b");

 

检查

  前面的博文已经介绍过jshint和csslint。如果要使用grunt中的插件,则需要在根目录下建立 .csslintrc 和 .jshintrc 文件,并设置它们的内容如下

//.csslintrc{"adjoining-classes":false,"box-sizing":false,"box-model":false,"compatible-vendor-prefixes": false,"floats":false,"font-sizes":false,"grandients":false,"important":false,"known-properties":false,"outline-none":false,"qualified-headings":false,"regex-selectors":false,"shorthand":false,"text-indent":false,"unique-headings":false,"universal-selector":false,"unqualified-attributes":false}//.jshintrc{"boss": false,"curly": true,"eqeqeq": true,"eqnull": true,"expr": true,"immed":true,"newcap":true,"noempty":true,"noarg":true,"undef":true,"regexp":true,"browser":false,"devel":true,"node":true}

  由于需要用到grunt-contrib-csslint和grunt-contrib-jshint插件,所以package.json的文件内容如下

{  "name": "project",  "version": "1.0.0",  "devDependencies": {"grunt": "^1.0.1","grunt-contrib-concat": "^1.0.1","grunt-contrib-cssmin": "^2.2.0","grunt-contrib-uglify": "^3.0.1","grunt-contrib-csslint": "^2.0.0","grunt-contrib-jshint": "^1.1.0"    
  }
}

  Gruntfile.js的配置文件如下

module.exports = function(grunt) {
  grunt.initConfig({
    pkg: grunt.file.readJSON('package.json'),
    concat: {
      options: {
        stripBanners: true,
        banner: '/*! <%= pkg.name %> - v<%= pkg.version %> - ' +'<%= grunt.template.today("yyyy-mm-dd") %> */'  },
      myCSSDist: {
        src: ['src/css/*.css'],
        dest: 'src/css/concat/<%= pkg.name %>-<%= pkg.version %>.css'  },
      myJSDist: {
        src: ['src/js/*.js'],
        dest: 'src/js/concat/<%= pkg.name %>-<%= pkg.version %>.js'  },      
    },
    cssmin:{
      options: {
        stripBanners: true,
        banner: '/* <%= grunt.template.today("yyyy-mm-dd") %> */'        
      },
      build:{
        src: 'src/css/concat/<%= pkg.name %>-<%= pkg.version %>.css',
        dest: 'dist/css/<%= pkg.name %>-<%= pkg.version %>.min.css'        
      }

    },
    uglify:{
      options: {
        stripBanners: true,
        banner: '/* <%= grunt.template.today("yyyy-mm-dd") %> */'        
      },
      build:{
        src: 'src/js/concat/<%= pkg.name %>-<%= pkg.version %>.js',
        dest: 'dist/js/<%= pkg.name %>-<%= pkg.version %>.min.js'        
      }
    },
    jshint:{
      options:{
        jshintrc:'.jshintrc'  },
      build:['Gruntfile.js','src/js/*.js']
    },
    csslint:{
      options:{
        csslintrc:'.csslintrc'  },
      build:['src/css/*.css']      
    }
  });
  grunt.loadNpmTasks('grunt-contrib-concat');
  grunt.loadNpmTasks('grunt-contrib-cssmin');
  grunt.loadNpmTasks('grunt-contrib-uglify');
  grunt.loadNpmTasks('grunt-contrib-jshint');
  grunt.loadNpmTasks('grunt-contrib-csslint');
  grunt.registerTask('default', ['jshint','csslint','concat','cssmin','uglify']);
};

  通过在命令行中使用npm install命令来安装插件

  然后执行命令grunt 

  可以看到'script1.js'文件中第1行缺少分号,修改后再执行命令grunt

 

监控

  grunt构建工具的自动化主要体现在grunt-contrib-watch插件上,该插件主要用于监听并执行对应的任务

  package.json的文件内容如下

{  "name": "project",  "version": "1.0.0",  "devDependencies": {"grunt": "^1.0.1","grunt-contrib-concat": "^1.0.1","grunt-contrib-csslint": "^2.0.0","grunt-contrib-cssmin": "^2.2.0","grunt-contrib-jshint": "^1.1.0","grunt-contrib-uglify": "^3.0.1","grunt-contrib-watch": "^1.0.0"
  }
}

  Gruntfile.js的配置文件如下

module.exports = function(grunt) {
  grunt.initConfig({
    pkg: grunt.file.readJSON('package.json'),
    concat: {
      options: {
        stripBanners: true,
        banner: '/*! <%= pkg.name %> - v<%= pkg.version %> - ' +'<%= grunt.template.today("yyyy-mm-dd") %> */'  },
      myCSSDist: {
        src: ['src/css/*.css'],
        dest: 'src/css/concat/<%= pkg.name %>-<%= pkg.version %>.css'  },
      myJSDist: {
        src: ['src/js/*.js'],
        dest: 'src/js/concat/<%= pkg.name %>-<%= pkg.version %>.js'  },      
    },
    cssmin:{
      options: {
        stripBanners: true,
        banner: '/* <%= grunt.template.today("yyyy-mm-dd") %> */'        
      },
      build:{
        src: 'src/css/concat/<%= pkg.name %>-<%= pkg.version %>.css',
        dest: 'dist/css/<%= pkg.name %>-<%= pkg.version %>.min.css'        
      }

    },
    uglify:{
      options: {
        stripBanners: true,
        banner: '/* <%= grunt.template.today("yyyy-mm-dd") %> */'        
      },
      build:{
        src: 'src/js/concat/<%= pkg.name %>-<%= pkg.version %>.js',
        dest: 'dist/js/<%= pkg.name %>-<%= pkg.version %>.min.js'        
      }
    },
    jshint:{
      options:{
        jshintrc:'.jshintrc'  },
      build:['Gruntfile.js','src/js/*.js']
    },
    csslint:{
      options:{
        csslintrc:'.csslintrc'  },
      build:['src/css/*.css']      
    },
    watch:{
      build:{
        files: ['src/js/*.js','src/css/*.css'],
        tasks: ['jshint','csslint','concat','cssmin','uglify'],
        options:{spawn:false}
      }
    }
  });
  grunt.loadNpmTasks('grunt-contrib-concat');
  grunt.loadNpmTasks('grunt-contrib-cssmin');
  grunt.loadNpmTasks('grunt-contrib-uglify');
  grunt.loadNpmTasks('grunt-contrib-jshint');
  grunt.loadNpmTasks('grunt-contrib-csslint');
  grunt.loadNpmTasks('grunt-contrib-watch');
  grunt.registerTask('default', ['jshint','csslint','concat','cssmin','uglify','watch']);
};

  通过在命令行中使用npm install命令来安装插件

  然后执行命令grunt

  修改'scrpt1.js'文件内容后,命令行自动显示如下

 

变动更新

  contrib-watch插件会监听需要处理的文件的变动,一旦有变动就会自动执行相应处理。但是它有一个问题,就是每当监听到一处变动时,就会大费周章地把所有被监听的文件都处理一遍

  而newer插件的作用是处理contrib-watch插件的毛病,让watch在监听到某个文件变动时,仅仅对变动的文件进行事务处理

  package.json的文件内容如下

{  "name": "project",  "version": "1.0.0",  "devDependencies": {"grunt": "^1.0.1","grunt-contrib-concat": "^1.0.1","grunt-contrib-csslint": "^2.0.0","grunt-contrib-cssmin": "^2.2.0","grunt-contrib-jshint": "^1.1.0","grunt-contrib-uglify": "^3.0.1","grunt-contrib-watch": "^1.0.0","grunt-contrib-requirejs": "^1.0.0","grunt-newer":"^1.3.0"
  }
}

  Gruntfile.js的配置文件如下

module.exports = function(grunt) {
  grunt.initConfig({
    pkg: grunt.file.readJSON('package.json'),
    concat: {
      options: {
        stripBanners: true,
        banner: '/*! <%= pkg.name %> - v<%= pkg.version %> - ' +'<%= grunt.template.today("yyyy-mm-dd") %> */'  },
      myCSSDist: {
        src: ['src/css/*.css'],
        dest: 'src/css/concat/<%= pkg.name %>-<%= pkg.version %>.css'  },
      myJSDist: {
        src: ['src/js/*.js'],
        dest: 'src/js/concat/<%= pkg.name %>-<%= pkg.version %>.js'  },      
    },
    cssmin:{
      options: {
        stripBanners: true,
        banner: '/* <%= grunt.template.today("yyyy-mm-dd") %> */'        
      },
      build:{
        src: 'src/css/concat/<%= pkg.name %>-<%= pkg.version %>.css',
        dest: 'dist/css/<%= pkg.name %>-<%= pkg.version %>.min.css'        
      }

    },
    uglify:{
      options: {
        stripBanners: true,
        banner: '/* <%= grunt.template.today("yyyy-mm-dd") %> */'        
      },
      build:{
        src: 'src/js/concat/<%= pkg.name %>-<%= pkg.version %>.js',
        dest: 'dist/js/<%= pkg.name %>-<%= pkg.version %>.min.js'        
      }
    },
    jshint:{
      options:{
        jshintrc:'.jshintrc'  },
      build:['Gruntfile.js','src/js/*.js']
    },
    csslint:{
      options:{
        csslintrc:'.csslintrc'  },
      build:['src/css/*.css']      
    },
    watch:{
      build:{
        files: ['src/js/*.js','src/css/*.css'],
        tasks: ['newer:jshint','newer:csslint','newer:concat','newer:cssmin','newer:uglify'],
        options:{spawn:false}
      }
    }
  });
  grunt.loadNpmTasks('grunt-contrib-concat');
  grunt.loadNpmTasks('grunt-contrib-cssmin');
  grunt.loadNpmTasks('grunt-contrib-uglify');
  grunt.loadNpmTasks('grunt-contrib-jshint');
  grunt.loadNpmTasks('grunt-contrib-csslint');
  grunt.loadNpmTasks('grunt-contrib-watch');
  grunt.loadNpmTasks('grunt-newer');
  grunt.registerTask('default', ['newer:jshint','newer:csslint','newer:concat','newer:cssmin','newer:uglify','watch']);
};

  执行命令grunt

grunt

  由于'script1.js'的内容发生了变化,所以重新合并了js文件,project-1.0.0.min.js的内容如下

/* 2017-06-09 */console.log("a"),console.log("b");

  由于css的内容没有发生变化,所以project-1.0.0.min.css的内容如下

/*! project - v1.0.0 - 2017-05-29 */body{margin:0}ul{list-style:none;margin:0;padding:0}

 

模块化

  下面说明grunt如何与requireJS配合使用,需要使用contrib-requirejs插件

npm install grunt-contrib-requirejs

  该插件的使用与r.js的使用类似,不需要建立单独的build.js文件,而是在Gruntfile.js中配置

  设置如下项目结构,src为开发环境,dist为上线环境

  在r.js中,可以使用'dir'配置项,将项目目录复制到一个新的地方。但是,在实际项目开发中,有许多文件与requirejs无关,也会被复制。所以,不应该使用'dir',而应该使用'out'配置项,只是将入口文件main.js打包到一个新的地方

  一般地,jQuery并不打包到main.js文件中。如果使用相对路径,打包前的main.js(开发环境)与jQuery存在路径依赖关系。打包后的main.js已经处于新的环境(上线环境),但此时仍然与开发环境的jQuery存在路径依赖关系,不符合逻辑

  所以,jQuery应该是上线环境的地址。由于打包后,main.js的config也会打包进行,新的main.js的位置发生变化,jQuery的相对路径也会变化。所以config应该写在index.html页面中。这样,在jQuery或main.js的路径发生变化时,可以进行改动

  因此,script1.js和script2.js这两个文件的内容如下

//script.jsdefine(['jquery'],function (){return $('div').height();
})//s2.jsdefine(['jquery'],function (){return $('div').width();
})

  main.js的内容如下

//main.jsrequire(['module/script1','module/script2'], function(a,b){
  console.log(a);
  console.log(b);
});

   index.html代码如下

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
<div></div>
<script data-main="main" src="dist/js/require.js?1.1.11"></script>
<script>require.config({
    baseUrl:'src/js',
    paths:{'jquery':'../../dist/js/jquery'}
});</script>
</body>
</html>

  package.json的文件内容如下

{  "name": "project",  "version": "1.0.0",  "devDependencies": {"grunt": "^1.0.1","grunt-contrib-concat": "^1.0.1","grunt-contrib-csslint": "^2.0.0","grunt-contrib-cssmin": "^2.2.0","grunt-contrib-jshint": "^1.1.0","grunt-contrib-uglify": "^3.0.1","grunt-contrib-watch": "^1.0.0","grunt-contrib-requirejs": "^1.0.0","grunt-newer":"^1.3.0"
  }
}

【contrib-requirejs插件配置】

  由于该插件打包后的文件,内容还是使用原来的路径关系。但是,开发和线上的路径并不一致。所以,要把可能会变化的路径设置为'baseUrl',其他的路径保持一致

  [注意]contrib-requirejs插件不能与newer插件混用

    requirejs: {
      compile: {
        options: {
          baseUrl: 'src/js',
          paths:{
            jquery:'../../dist/js/jquery'  },
          name: 'main',       
          out:'dist/js/main.js',
          exclude: ['jquery']
        }
      }
    }

  Gruntfile.js的配置文件如下

module.exports = function(grunt) {
  grunt.initConfig({
    pkg: grunt.file.readJSON('package.json'),
    concat: {
      options: {
        stripBanners: true,
        banner: '/*! <%= pkg.name %> - v<%= pkg.version %> - ' +'<%= grunt.template.today("yyyy-mm-dd") %> */'  },
      myCSSDist: {
        src: ['src/css/*.css'],
        dest: 'src/css/concat/<%= pkg.name %>-<%= pkg.version %>.css'  }
    },
    cssmin:{
      options: {
        stripBanners: true,
        banner: '/* <%= grunt.template.today("yyyy-mm-dd") %> */'        
      },
      build:{
        src: 'src/css/concat/<%= pkg.name %>-<%= pkg.version %>.css',
        dest: 'dist/css/<%= pkg.name %>-<%= pkg.version %>.min.css'        
      }

    },
    jshint:{
      options:{
        jshintrc:'.jshintrc'  },
      build:['Gruntfile.js','src/js/*.js']
    },
    csslint:{
      options:{
        csslintrc:'.csslintrc'  },
      build:['src/css/*.css']      
    },
    requirejs: {
      compile: {
        options: {
          baseUrl: 'src/js',
          paths:{
            jquery:'../../dist/js/jquery'  },
          name: 'main',       
          out:'dist/js/main.js',
          exclude: ['jquery']
        }
      }
    },
    watch:{
      build:{
        files: ['src/js/*.js','src/css/*.css'],
        tasks: ['newer:jshint','newer:csslint','newer:concat','newer:cssmin','newer:uglify','requirejs'],
        options:{spawn:false}
      }
    }
  });
  grunt.loadNpmTasks('grunt-contrib-concat');
  grunt.loadNpmTasks('grunt-contrib-cssmin');
  grunt.loadNpmTasks('grunt-contrib-jshint');
  grunt.loadNpmTasks('grunt-contrib-csslint');
  grunt.loadNpmTasks('grunt-contrib-requirejs');
  grunt.loadNpmTasks('grunt-contrib-watch');
  grunt.loadNpmTasks('grunt-newer');

  grunt.registerTask('default', ['newer:jshint','newer:csslint','newer:concat','newer:cssmin','requirejs','watch']);
};

  执行命令grunt

  更改index.html页面如下,依然能正常显示

<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>Document</title></head><body><div></div><script data-main="main" src="dist/js/require.js?1.1.11"></script><script>require.config({
    baseUrl:'dist/js',
    paths:{'jquery':'../../dist/js/jquery'}
});</script></body></html>

 

 

以上是什么是Grunt?对他的详细介绍的详细内容。更多信息请关注PHP中文网其他相关文章!

声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
Python vs. JavaScript:社区,图书馆和资源Python vs. JavaScript:社区,图书馆和资源Apr 15, 2025 am 12:16 AM

Python和JavaScript在社区、库和资源方面的对比各有优劣。1)Python社区友好,适合初学者,但前端开发资源不如JavaScript丰富。2)Python在数据科学和机器学习库方面强大,JavaScript则在前端开发库和框架上更胜一筹。3)两者的学习资源都丰富,但Python适合从官方文档开始,JavaScript则以MDNWebDocs为佳。选择应基于项目需求和个人兴趣。

从C/C到JavaScript:所有工作方式从C/C到JavaScript:所有工作方式Apr 14, 2025 am 12:05 AM

从C/C 转向JavaScript需要适应动态类型、垃圾回收和异步编程等特点。1)C/C 是静态类型语言,需手动管理内存,而JavaScript是动态类型,垃圾回收自动处理。2)C/C 需编译成机器码,JavaScript则为解释型语言。3)JavaScript引入闭包、原型链和Promise等概念,增强了灵活性和异步编程能力。

JavaScript引擎:比较实施JavaScript引擎:比较实施Apr 13, 2025 am 12:05 AM

不同JavaScript引擎在解析和执行JavaScript代码时,效果会有所不同,因为每个引擎的实现原理和优化策略各有差异。1.词法分析:将源码转换为词法单元。2.语法分析:生成抽象语法树。3.优化和编译:通过JIT编译器生成机器码。4.执行:运行机器码。V8引擎通过即时编译和隐藏类优化,SpiderMonkey使用类型推断系统,导致在相同代码上的性能表现不同。

超越浏览器:现实世界中的JavaScript超越浏览器:现实世界中的JavaScriptApr 12, 2025 am 12:06 AM

JavaScript在现实世界中的应用包括服务器端编程、移动应用开发和物联网控制:1.通过Node.js实现服务器端编程,适用于高并发请求处理。2.通过ReactNative进行移动应用开发,支持跨平台部署。3.通过Johnny-Five库用于物联网设备控制,适用于硬件交互。

使用Next.js(后端集成)构建多租户SaaS应用程序使用Next.js(后端集成)构建多租户SaaS应用程序Apr 11, 2025 am 08:23 AM

我使用您的日常技术工具构建了功能性的多租户SaaS应用程序(一个Edtech应用程序),您可以做同样的事情。 首先,什么是多租户SaaS应用程序? 多租户SaaS应用程序可让您从唱歌中为多个客户提供服务

如何使用Next.js(前端集成)构建多租户SaaS应用程序如何使用Next.js(前端集成)构建多租户SaaS应用程序Apr 11, 2025 am 08:22 AM

本文展示了与许可证确保的后端的前端集成,并使用Next.js构建功能性Edtech SaaS应用程序。 前端获取用户权限以控制UI的可见性并确保API要求遵守角色库

JavaScript:探索网络语言的多功能性JavaScript:探索网络语言的多功能性Apr 11, 2025 am 12:01 AM

JavaScript是现代Web开发的核心语言,因其多样性和灵活性而广泛应用。1)前端开发:通过DOM操作和现代框架(如React、Vue.js、Angular)构建动态网页和单页面应用。2)服务器端开发:Node.js利用非阻塞I/O模型处理高并发和实时应用。3)移动和桌面应用开发:通过ReactNative和Electron实现跨平台开发,提高开发效率。

JavaScript的演变:当前的趋势和未来前景JavaScript的演变:当前的趋势和未来前景Apr 10, 2025 am 09:33 AM

JavaScript的最新趋势包括TypeScript的崛起、现代框架和库的流行以及WebAssembly的应用。未来前景涵盖更强大的类型系统、服务器端JavaScript的发展、人工智能和机器学习的扩展以及物联网和边缘计算的潜力。

See all articles

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热门文章

R.E.P.O.能量晶体解释及其做什么(黄色晶体)
4 周前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳图形设置
4 周前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您听不到任何人,如何修复音频
4 周前By尊渡假赌尊渡假赌尊渡假赌
WWE 2K25:如何解锁Myrise中的所有内容
1 个月前By尊渡假赌尊渡假赌尊渡假赌

热工具

安全考试浏览器

安全考试浏览器

Safe Exam Browser是一个安全的浏览器环境,用于安全地进行在线考试。该软件将任何计算机变成一个安全的工作站。它控制对任何实用工具的访问,并防止学生使用未经授权的资源。

EditPlus 中文破解版

EditPlus 中文破解版

体积小,语法高亮,不支持代码提示功能

DVWA

DVWA

Damn Vulnerable Web App (DVWA) 是一个PHP/MySQL的Web应用程序,非常容易受到攻击。它的主要目标是成为安全专业人员在合法环境中测试自己的技能和工具的辅助工具,帮助Web开发人员更好地理解保护Web应用程序的过程,并帮助教师/学生在课堂环境中教授/学习Web应用程序安全。DVWA的目标是通过简单直接的界面练习一些最常见的Web漏洞,难度各不相同。请注意,该软件中

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

适用于 Eclipse 的 SAP NetWeaver 服务器适配器

适用于 Eclipse 的 SAP NetWeaver 服务器适配器

将Eclipse与SAP NetWeaver应用服务器集成。