如何保留特定注释(如 legal)并删除 console 语句

解读

在国内前端面试中,这道题表面问“配置”,实则考察三点:

  1. 你是否理解构建产物合规性(license、法律免责必须保留);
  2. 你是否熟悉Grunt 插件的协同机制(uglify、babel、strip 多插件组合);
  3. 你是否具备**“最小侵入”思维**——只删 console,不破坏源码映射、不误杀合法日志。
    回答时务必给出可落地的 Gruntfile 片段,并解释“为什么这样写”而不是“能跑就行”。

知识点

  • uglify-es / terser 的 output.comments 正则过滤策略
  • babel-plugin-transform-remove-console 的“选择性移除”与 sourcemap 无损
  • grunt-strip-commentsgrunt-contrib-uglify 的冲突规避(双插件顺序)
  • banner 模板与 @preserve/@license 标记在国内版权审计中的法律效力
  • Grunt 任务链:babel → strip → uglify,保证 AST 先干净再压缩
  • sourcemap 同步更新,否则线上报错无法定位
  • CI 卡点:在 gitlab-ci 或 GitHub Actions 里加 grunt legal-check 任务,防止后人改配置误删注释

答案

  1. 安装依赖
npm i -D grunt-contrib-uglify@^5 babel-plugin-transform-remove-console grunt-babel @babel/core
  1. Gruntfile.js 核心配置
module.exports = function(grunt) {
  grunt.initConfig({
    babel: {
      dist: {
        files: [{
          expand: true,
          cwd: 'src',
          src: '**/*.js',
          dest: '.tmp'
        }],
        options: {
          plugins: [['transform-remove-console', { exclude: ['error', 'warn'] }]]
        }
      }
    },
    uglify: {
      options: {
        output: {
          comments: /^\**!|@preserve|@license|legal/i   // 保留带 legal 的注释
        },
        banner: '/*! <%= pkg.name %> v<%= pkg.version %> | (c) <%= grunt.template.today("yyyy") %> */'
      },
      dist: {
        files: [{
          expand: true,
          cwd: '.tmp',
          src: '**/*.js',
          dest: 'dist'
        }]
      }
    }
  });

  grunt.loadNpmTasks('grunt-babel');
  grunt.loadNpmTasks('grunt-contrib-uglify');
  grunt.registerTask('default', ['babel', 'uglify']);
};
  1. 验证
grunt default
grep -n console dist/*.js      # 应无结果
grep -i legal dist/*.js        # 应仍保留

拓展思考

  • 若项目用 TypeScript,把 babel 换成 grunt-ts + ts-loader,并在 tsconfig.json 里同样配置 remove-console 插件,保证类型检查与移除一次性完成。
  • 第三方库(如 lodash)不想删其 console,可在 babel 配置里加 ignore: ['node_modules/**'],再用 webpack 的 externals 把库分离出去,避免合规风险。
  • 国内很多甲方要求**“代码可审计”**,此时需把 uglify.options.sourceMap 设为 true 并上传 .map 到私有源,审计人员可还原原始代码验证 legal 注释未被误删。
  • 如果后续迁移到 Vite/Rollup,可用 rollup-plugin-terserformat.comments 保持相同正则,实现配置知识无损耗迁移,体现你对工程化长期演进的思考。