Grunt 本身没有单一的“打包命令”。

Grunt 是一个任务运行器,它的核心思想是:你通过一个名为 Gruntfile.js 的配置文件来定义各种“任务”,然后通过 grunt 命令来执行这些任务,所谓的“打包”,只是你定义的一个或多个任务(比如合并文件、压缩代码等)的集合。
要执行 Grunt 打包,你需要两步:
- 配置
Gruntfile.js:告诉 Grunt 你要做什么。 - 在终端运行
grunt命令:让 Grunt 去执行你在配置文件中定义的任务。
第一步:准备工作(安装 Grunt)
在运行任何命令之前,确保你的项目已经正确配置了 Grunt 环境。
-
全局安装 Grunt CLI (命令行工具) 这个工具用于在全局任何地方调用
grunt命令。
(图片来源网络,侵删)npm install -g grunt-cli
-
在项目中安装 Grunt 和相关插件 进入你的项目根目录,执行以下命令,这会创建一个
package.json文件(如果还没有的话)。npm init -y
-
安装 Grunt 核心包
npm install grunt --save-dev
-
安装你需要的插件 如果你想合并和压缩 JS 文件,需要安装
grunt-contrib-concat和grunt-contrib-uglify插件。npm install grunt-contrib-concat grunt-contrib-uglify --save-dev
--save-dev会把这些依赖添加到package.json的devDependencies中。
(图片来源网络,侵删)
第二步:配置 Gruntfile.js
这是 Grunt 的核心,在项目根目录下创建一个名为 Gruntfile.js 的文件,并编写配置代码。
下面是一个典型的 Gruntfile.js 示例,它完成了两个常见的“打包”任务:
- concat:合并多个 JS 文件。
- uglify:压缩合并后的 JS 文件。
// Gruntfile.js
module.exports = function(grunt) {
// 1. 项目配置
grunt.initConfig({
// 从 package.json 文件中读取元数据
pkg: grunt.file.readJSON('package.json'),
// 2. concat 任务配置:合并 JS 文件
concat: {
options: {
banner: '/*! <%= pkg.name %> - v<%= pkg.version %> - ' +
'<%= grunt.template.today("yyyy-mm-dd") %> */\n', // 文件头部注释
stripBanners: true, // 去除源文件中的注释
},
dist: {
src: [
'src/js/*.js', // 要合并的 JS 文件路径(支持通配符)
'src/js/init.js' // 也可以指定具体文件
],
dest: 'dist/<%= pkg.name %>.concat.js' // 合并后的输出文件路径
}
},
// 3. uglify 任务配置:压缩 JS 文件
uglify: {
options: {
banner: '/*! <%= pkg.name %> - v<%= pkg.version %> - ' +
'<%= grunt.template.today("yyyy-mm-dd") %> */\n',
sourceMap: true // 生成 source map 文件
},
dist: {
files: {
'dist/<%= pkg.name %>.min.js' // 压缩后的输出文件路径
: ['<%= concat.dist.dest %>'] // 输入是 concat 任务的输出结果
}
}
},
// 4. watch 任务配置:监听文件变化,自动执行任务
watch: {
js: {
files: ['src/js/**/*.js'], // 监听的文件
tasks: ['concat', 'uglify'], // 文件变化时执行的任务
options: {
spawn: false, // 避免重复执行
}
}
}
});
// 5. 加载 Grunt 插件
// grunt.loadNpmTasks('grunt-contrib-concat');
// grunt.loadNpmTasks('grunt-contrib-uglify');
// grunt.loadNpmTasks('grunt-contrib-watch');
// 使用 grunt.loadNpmTasks 需要一个个加载,比较麻烦。
// 更好的方式是使用 grunt.loadTasks 加载 tasks 文件夹,或者使用插件自动加载。
// 对于现代 Grunt,推荐使用下面这种简写方式:
grunt.loadNpmTasks('grunt-contrib-concat');
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-contrib-watch');
// 或者,如果你安装了 `grunt-contrib-*` 系列插件,可以自动加载
// grunt.loadNpmTasks('grunt-contrib-*'); // 这种方式需要 Grunt 0.4.5+ 版本支持
// 6. 注册任务
// 这是执行打包命令的核心
grunt.registerTask('default', ['concat', 'uglify']); // 默认任务,直接执行 grunt 即可
grunt.registerTask('build', ['concat', 'uglify']); // 自定义任务,执行 grunt build
grunt.registerTask('dev', ['watch']); // 开发模式,执行 grunt dev
};
第三步:运行 Grunt 命令
现在你的 Gruntfile.js 已经配置好了,打开终端,确保在项目根目录下,就可以运行命令了。
假设你的项目结构如下:
my-project/
├── dist/ // 输出目录
├── node_modules/
├── src/
│ └── js/
│ ├── file1.js
│ ├── file2.js
│ └── init.js
├── Gruntfile.js
└── package.json
执行默认任务
如果你在 registerTask 中将第一个参数设置为 'default',那么直接运行 grunt 命令就会执行它关联的任务列表。
# 在项目根目录下执行 grunt
执行后,Grunt 会依次运行 concat 和 uglify 任务,你会在 dist/ 目录下看到生成的合并文件(.concat.js)和压缩文件(.min.js)。
执行指定的自定义任务
你可以在 registerTask 中定义一个任务别名,然后通过别名来执行。
# 执行名为 'build' 的任务,它和 'default' 做的事情一样 grunt build
执行单个任务
你也可以只执行配置文件中的某一个任务,这在调试时非常有用。
# 只执行 concat 任务 grunt concat # 只执行 uglify 任务 grunt uglify
执行多个任务
你可以一次性执行多个任务,用空格隔开。
# 先执行 concat,再执行 uglify # 这和 grunt build 或 grunt default 效果一样 grunt concat uglify
开发模式任务
我们配置了一个 watch 任务,它可以监听文件变化并自动重新打包。
# 运行开发模式任务 grunt dev
执行后,Grunt 会进入监听状态,当你修改 src/js/ 目录下的任何 .js 文件并保存时,它会自动在后台运行 concat 和 uglify 任务,无需你手动再次输入 grunt 命令。
| 命令 | 描述 | 对应 Gruntfile 配置 |
|---|---|---|
grunt |
默认打包命令,执行 registerTask 中别名为 'default' 的任务列表。 |
grunt.registerTask('default', ['concat', 'uglify']); |
grunt build |
执行自定义的 build 任务,通常和默认任务功能相同。 |
grunt.registerTask('build', ['concat', 'uglify']); |
grunt concat |
只执行合并文件任务。 | grunt.registerTask('concat', ...); (通常不需要单独注册) |
grunt uglify |
只执行压缩文件任务。 | grunt.registerTask('uglify', ...); (通常不需要单独注册) |
grunt dev |
进入开发模式,监听文件变化并自动打包。 | grunt.registerTask('dev', ['watch']); |
核心要点:
grunt命令本身是执行器,它执行的是你在Gruntfile.js中定义好的任务。- “打包”是一个概念,它通过组合
concat(合并)、uglify/cssmin(压缩)、copy(复制)等具体任务来实现。 grunt.registerTask是将一系列操作打包成一个可执行命令的关键。
