跳至主要內容

记一次项目中自动去除console.log打印(非正常webpack、vite打包环境)

菜鸡小谢原创大约 6 分钟gitjavascript

前言

前不久接到一个需求,为了保证信息安全的问题,需要去除项目中所有的console.log打印。常见的通过webpack、vite打包编译的项目都有对应的插件,比如babel插件[babel-plugin-transform-remove-console](https://www.npmjs.com/package/babel-plugin-transform-remove-console)、webpack插件[terser-webpack-plugin](https://www.npmjs.com/package/terser-webpack-plugin/v/1.4.5)等。但是我们的项目是属于php的前后端不分离项目,这应该怎么办呢?只能靠自己手搓nodejs脚本了。(需要支持node环境)

思路

引入npm包管理工具,利用nodejs脚本修改文件内容,去除所有的console.log。然后利用git hooks脚本实现自动化,再然后通过lint-staged实现监听变化的文件。

npm初始化

npm init

然后根据命令行输入一系列命令,最后生成package.json文件。

nodejs脚本文件

const path = require('path');
const fs = require('fs');

// path.resolve() 方法会把一个路径或路径片段的序列解析为一个绝对路径。遇到绝对路径时会重新开始解析
// path.join() 方法使用平台特定的分隔符把全部给定的 path 片段连接到一起,并规范化生成的路径
function pathJudge(pathStr) {
 pathStr = path.resolve(__dirname, pathStr);
 
 const stats = fs.statSync(pathStr);
 // 判断路径是否是文件夹
 if (!stats.isDirectory()) {
  removeConsoleFile(pathStr);
 } else {
  // 读取文件夹
  const files = fs.readdirSync(pathStr);
  
  files.forEach(file => {
   const filePath = path.join(pathStr, file);
   pathJudge(filePath);
  })
 }
}


function removeConsoleFile(filePath) {
 const stats = fs.statSync(filePath);
 if (stats.isDirectory()) {
  return
 }
 if (stats.isFile() && (filePath.endsWith('.js') || filePath.endsWith('.php'))) {
  let content = fs.readFileSync(filePath, 'utf-8');
  content = content.replace(/console.log\((.*)\);?/g, '');
  fs.writeFileSync(filePath, content, 'utf-8');
 }
}


function main() {
 //这里是用来判断是否执行循环目录
 let filePath = process.env.NODE_PATH;
 
 if (filePath) {
  pathJudge(filePath);
 } else {
  // 这里是通过lint-staged拿到的变化的文件  
  filePath = process.argv.slice(2);
  filePath.forEach(filePath => {
   pathJudge(filePath);
  })
 }
}

main();



脚本自动化执行

  1. git hooks介绍

    Git hooks 是 Git 提供的一种机制,允许在特定事件发生时执行自定义脚本。它们可以让你在 Git 的生命周期中插入自定义的行为,这能帮助开发团队在代码提交、合并、推送等操作时进行自动化处理,如代码格式化、单元测试、静态检查等。以下是常见的 Git hooks 类型:

    Hook 名称触发时机用途
    applypatch-msggit am 处理补丁文件时检查补丁文件的提交信息
    pre-applypatchgit am 应用补丁之前执行动作,如消息通知
    post-applypatchgit am 应用补丁之后通常用于通知用户补丁应用完成
    pre-commit提交代码之前检查代码,如运行测试或代码风格检查
    prepare-commit-msggit commit 生成提交信息之前修改生成的提交信息模板
    commit-msggit commit 编写提交信息之后检查或修改提交信息
    post-commit提交成功后通知用户或执行后续动作,如触发 CI/CD 流程
    pre-rebasegit rebase 之前允许钩子脚本在变基前停止执行或执行前准备动作
    post-rewritegit commit --amendgit rebase 等命令重写提交记录后通知用户提交记录被重写
    pre-pushgit push 之前运行任务,如发布前检查或测试
    pre-receive远程仓库接收到推送前检查推送内容或拒绝推送
    update远程仓库接收到推送,分支更新时检查更新内容或拒绝更新
    post-receive远程仓库接收到推送后执行后续任务,如部署或通知
    post-updategit push 更新成功后通常用于更新服务端的引用或通知
    reference-transaction引用被创建、更新或删除时跟踪引用变化
    push-to-checkout远程推送直接签出到工作目录时更新工作目录内容前执行动作
    pre-auto-gcgit gc --auto 之前在自动垃圾回收前执行动作
    post-checkout切换分支或恢复文件之后通知用户或执行后续任务,如重建依赖
    post-merge合并完成后通知用户或执行后续任务,如重新编译
    post-rewritegit commit --amendgit rebase 等命令重写提交记录后通知用户提交记录被重写
    pre-reflog更新引用日志前执行检查或准备工作
    post-reflog更新引用日志后通知用户或执行后续任务
    post-index-change索引文件被更改后通知用户或执行后续任务

    其中pre-commit这个hooks是我们所需要使用的。

  2. husky使用

    husky官网open in new window

    首先安装husky

    npm install --save-dev husky
    

    初始化husky,会在package.json生成一个script命令

    npx husky init
    
    {
      "scripts": {
        "prepare": "husky"
      }
    }
    

    执行这个命令 npm run prepare,会在 .husky/ 目录中创建一个 pre-commit 文件,在这个里面可以执行shell命令,如何npm run xxx等等。(husky4以上版本

    比如我们要执行这个node脚本呢,就可以在这个文件里面写一下命令就会在提交前执行我们的node脚本。

    node ./remove-console.js
    

    这样我们的工作量基本完成了90%了。接下来我们用lint-staged来完成只去除修改过的文件的console。

  3. lint-staged使用

    官网open in new window

    首先install

    npm install --save-dev lint-staged # requires further setup
    

    package.json加入以下代码

      "lint-staged": {
        "*.{js,php}": [
          "npm run remove-console"
        ]
      }
    

    前面创建的 pre-commit文件加入以下代码

    npx lint-staged
    

    nodejs脚本中 process.argv.slice(2)可以拿到变化的文件数组,遍历即可。process_argv介绍open in new window

    现在就完成所有的工作量了。

补充

  1. 设置node运行环境变量

    windows cmd中:

    set NODE_ENV=production && node app.js
    

    windows powershell中:

    $env:NODE_ENV="production"; node app.js
    

    macOS/Linux中:

    export NODE_ENV=production node app.js
    

    node脚本可以通过 process.env.xxx拿到对应的值。

    这样多端不同意很不方便,我们可以使用cross-envopen in new window这个库统一规范。

    使用方法:

    cross-env NODE_PATH=./addons/fecmall/fecro/ node remove-console.js
    
  2. commitizen使用

    团队开发时,可以使用commitizen规范提交日志。

    首先安装对应的包。全局安装commitizen

    npm install -g commitizen
    

    安装cz-conventional-changelogopen in new window commitizen 适配器。(还有一个cz-customizable可以定制提交规范)

    commitizen init cz-conventional-changelog --save --save-exact  #--save-exact 代表版本,不会加^和~
    

    这样package.json文件会增加以下内容

    "config": {
        "commitizen": {
          "path": "./node_modules/cz-conventional-changelog"
        }
      },
    

    这样我们 git add之后,然后执行 git cz就会出现以下内容。

    image-20240817153750652
    image-20240817153750652

    这样就大功告成啦。