编写一个仅打印“Hello Grunt”的自定义任务并注册为默认任务
解读
在国内前端面试中,这道题看似“Hello World”级别,却常被用来快速验证候选人是否真正动手写过 Gruntfile,而非只会“npm install”。
面试官真正想确认三点:
- 你是否知道任务必须定义在 module.exports 函数里,而非随意写;
- 你是否会用grunt.registerTask 把任务挂到默认队列;
- 你是否理解同步/异步任务写法(虽然本题只需同步,但答出异步签名会加分)。
答得太简单(直接 console.log)会被追问“如果任务里出现异步逻辑怎么办”;答得太复杂(引入插件、多任务)又显得“杀鸡用牛刀”。最稳妥的是给出最小可运行示例,并口头补充异步写法与错误处理思路。
知识点
- Gruntfile 基本结构:module.exports = function(grunt) { … }
- grunt.registerTask(name, description, fn):注册自定义任务,description 可省略但国内代码审查普遍要求写,方便 grunt --help 输出。
- 任务函数签名:function() 为同步;function() { var done = this.async(); … done(); } 为异步。面试时口头提到 done 能体现你对构建流程的严谨理解。
- 默认任务:grunt.registerTask('default', ['xxx']),数组写法可扩展,即使当前只有一个任务也建议用数组,方便后续追加。
- 终端验证:npx grunt 或 npm run grunt 必须能直接看到“Hello Grunt”输出,国内 CI 环境普遍无全局 grunt-cli,需用 npx。
答案
Gruntfile.js(位于项目根目录,与 package.json 同级):
module.exports = function(grunt) {
// 自定义任务
grunt.registerTask('hello', '打印 Hello Grunt', function() {
grunt.log.writeln('Hello Grunt');
});
// 注册为默认任务
grunt.registerTask('default', ['hello']);
};
验证步骤(国内镜像源已配置):
# 安装 grunt 本地依赖
npm i -D grunt
# 运行默认任务
npx grunt
终端输出:
Running "hello" task
Hello Grunt
Done.
拓展思考
- 异步场景:若任务里需拉取远程配置,可改为
var done = this.async(); request(url, function(err, res) { … done(err); });
错误优先回调是 Grunt 任务的经典模式,面试时主动提及可展示老派功底。 - 多任务组合:国内项目常把 hello 任务当作“前置检查”钩子,再串联 clean、eslint、webpack 等。默认任务写成数组即可无痛扩容,例如
grunt.registerTask('default', ['env:dev', 'hello', 'eslint']); - 性能陷阱:Grunt 基于临时文件,大项目下 IO 频繁。答完基础题后可顺口对比 gulp 的流式与 webpack 的依赖图,体现你对构建工具的横向认知,但切忌踩一捧一,用“场景差异”收尾更显专业。