使用 grunt-init 创建项目时如何自定义模板变量
解读
在国内前端面试中,**“grunt-init 自定义模板变量”**常被用来考察候选人对 Grunt 生态深度定制能力。
面试官真正想听的是:
- 你是否理解 grunt-init 的模板替换机制(基于 <%= prop %> 占位符);
- 你是否能不改动全局模板的前提下,为团队沉淀一套“私有可复用”模板;
- 你是否知道prompt.json 与 template.js 的配合方式,以及如何把公司规范(如私有 npm 源、CDN 路径、内部 GitLab 地址)注入到新建项目里。
答不到“私有模板目录 + prompt 扩展 + 默认值回写”这三点,基本会被判定为“只会用现成模板”。
知识点
- grunt-init 模板目录结构
- root/:原样拷贝的文件
- template.js:唯一入口,通过 init.process 控制文件渲染与重命名
- template/:含 <%= var %> 占位符的待渲染文件
- 变量来源优先级
- 内置变量(name、author、email 等)
- prompt.json 自定义交互字段(可被 init.prompts 扩展)
- defaults.json 静默默认值(适合 CI 场景)
- 自定义流程
- 本地模板放置路径:~/.grunt-init/xxx(Windows 下为 %USERPROFILE%.grunt-init\xxx)
- 在 template.js 里用 init.prompts 追加问题,并通过 init.process 把答案写入 props
- 模板文件中用 <%= props.pluginName %> 形式取值,支持 .camelCase、.slugify 等 Underscore 模板函数
- 国内常见定制项
- registry=https://registry.npmmirror.com
- gitUrl 模板变量指向内部 GitLab 组
- cdnPrefix 指向公司统一静态资源域名
- 调试技巧
- 加 --debug 参数可打印 props 对象,确认变量是否注入成功
- 使用 init.writePackageJSON 二次回写,保证 package.json 字段与团队规范完全一致
答案
步骤如下:
- 在本地私有模板目录新建文件夹,例如 ~/.grunt-init/vue-mobile。
- 创建 prompt.json,追加公司需要的变量:
{ "registry": { "type": "input", "message": "私有 npm 源地址", "default": "https://registry.npmmirror.com" }, "cdnPrefix": { "type": "input", "message": "静态资源 CDN 前缀", "default": "//static.example.com" } } - 在 template.js 中把自定义字段合并到 props:
exports.template = function(grunt, init, done) { init.process({type: 'jquery'}, [ init.prompt('name'), init.prompt('registry'), init.prompt('cdnPrefix') ], function(err, props) { props.devDependencies = {grunt: '^1.6.0'}; // 把 registry 写入 .npmrc 模板 props.npmrc = 'registry=' + props.registry; // 生成文件 var files = init.filesToCopy(props); init.copyAndProcess(files, props); // 二次回写 package.json init.writePackageJSON('package.json', props, function(pkg) { pkg.cdnPrefix = props.cdnPrefix; return pkg; }); done(); }); }; - 在 template/.npmrc 中写入:
<%= npmrc %> - 运行 grunt-init vue-mobile,交互阶段会提示输入 registry 与 cdnPrefix,回车后所有占位符被替换,项目即按公司规范初始化完成。
拓展思考
- 如何共享私有模板?
把模板目录推送到内部 GitLab,再写个 CLI 脚本:git clone 到 ~/.grunt-init/ 并自动重命名,实现“一键同步团队模板”。 - 如何让 grunt-init 与 Yeoman 共存?
老项目用 grunt-init 维护,新项目用 Yeoman generator,但统一在 meta 文件里记录模板版本号,保证构建产物可追踪。 - 如何在 CI 中无交互使用?
在 defaults.json 中预置所有变量,执行 grunt-init xxx --default,配合 Docker 可在 5 秒内拉起一个标准化前端项目。