前言
grunt官网称之为JavaScript世界的构建工具,一个基于nodeJs的前端自动化工具,可以用来处理一些反复重复的任务,比如压缩、编译、单元测试等。
基础
使用grunt需要安装grunt和grunt-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.js和js/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中分别设置mangle和 preserveComments,不混淆变量名和不删除注释,再添加一个尾部注释,最后在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.js和b.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)
看到打印的输出内容,表明压缩没问题。