描述一套可落地的 src/dist/build 目录划分最佳实践

解读

面试官想验证三件事:

  1. 你是否真正用 Grunt 跑过完整的前端交付链路,而不是“配过几个插件”;
  2. 你能否把“开发效率”“部署安全”“团队协作”三个维度同时落地到目录结构里;
  3. 你对国内常见约束(CI 只认指定目录、测试部只拉包、运维强制增量发布等)有没有体感。
    因此,“可落地” 比“好看”更重要:必须让后端、测试、运维不经解释就能一键定位资源。

知识点

  1. src 是“只读源码区”,任何插件生成的临时文件都不落进来,保证 git diff 干净。
  2. build 是“本地工作区”,Grunt 中间产物(.tmp、.cache、sourcemap 未压缩版)全放这里,不被 git 追踪,但可被 .gitignore 显式豁免部分文件(如测试覆盖率报告需归档)。
  3. dist 是“交付物区”,只放上线所需的最小集合,目录名必须固定(国内 Jenkins、GitLab CI 默认找 dist),且要支持“增量覆盖”与“版本回滚”两套策略。
  4. Gruntfile.js 本身放在项目根,任务按“阶段”划分:clean:build、clean:dist、build:dev、build:prod、build:test,杜绝任务链直接写死路径,所有路径用 grunt.config.merge 注入,方便不同环境复用。
  5. 国内常见“静态资源 CDN 加速”要求文件名带 hash,因此 dist 里必须保留 manifest.json(key 为原始名,value 为 hash 名),供后端模板引擎一次性注入。

答案

以下目录树可直接搬进 2024 年的 Vue2/Vue3、jQuery、React15+ 等任何国内项目,零改造即可通过阿里、腾讯、字节等流水线检测。

project-root
├─ Gruntfile.js
├─ package.json
├─ .gitignore
├─ src
│ ├─ pages
│ │ ├─ index
│ │ │ ├─ index.html
│ │ │ ├─ index.js
│ │ │ └─ index.less
│ ├─ components
│ ├─ utils
│ ├─ assets
│ │ ├─ images
│ │ └─ fonts
│ └─ mock
├─ build
│ ├─ .tmp(grunt-contrib-clean 自动创建,git 忽略)
│ ├─ coverage(nyc 报告,git 忽略,但 CI 会归档)
│ └─ stats(webpack-bundle-analyzer 静态图,可选提交)
└─ dist
├─ static
│ ├─ js
│ ├─ css
│ └─ img
├─ mock(若需“本地联调包”一起交付,可开关)
└─ manifest.json(grunt-filerev-summary 自动生成)

Grunt 任务编排(核心片段)

  1. grunt.registerTask('default', ['clean:build', 'eslint:src', 'babel:tmp', 'less:tmp', 'filerev:dist', 'usemin:dist', 'copy:dist', 'clean:tmp'])
  2. 路径变量统一放在 grunt.initConfig 外
    const SRC = 'src';
    const BUILD = 'build/.tmp';
    const DIST = 'dist';
    这样测试同学改 mock 路径、运维改 CDN 路径,只需改一行常量,无需读懂 Gruntfile

上线流程

  1. 本地 npm run build 后,只有 dist 目录会被 tar -zcvf 打包
  2. 上传到阿里云 OSS 或腾讯 COS,文件名即版本号(package.json 的 version);
  3. 回滚时,运维直接拉取对应 version 的 tar 包解压覆盖,无需重新构建

拓展思考

  1. 微前端场景:若子应用独立仓库,src 下再分 sub-app-a、sub-app-b,dist 里产出 sub-app-a.html、sub-app-b.html,主基座通过 manifest.json 动态加载,Grunt 只需多一个 grunt-concurrent 并发任务即可。
  2. SSR 同构:Node 层需要 sourcemap 定位错误,可在 build 目录保留 *.js.map,但 dist 里删除,通过 grunt-contrib-compress 选择性打两份包(web.zip、node.zip),实现“同构不同产”。
  3. 国内合规:若涉及个人敏感信息图片,grunt-contrib-imagemin 之后加 grunt-contrib-webp,把原图留在 build 供审计,dist 只放 webp,满足“最小可用”原则