使用create-react-app 脚手架创建的项目,一般默认是在chrom中进行调试,但是如果你想要在vscode中进行调试,就要做相应的配置,并且原有的日志功能也不是很完善,所以下面我们就想办法让React项目在vscode中进行调试,并且改进一下console.log的功能
首先使用create-react-app 脚手架创建一个react项目 打开控制台,并进入相应的目录,使用命令
npx create-react-app my-app --template typescript项目名称 my-app 后面的参数–template typescript 让项目使用typescript 项目创建完成后,进入项目目录,运行
npm install等待包安装完成后,运行
npm start项目会自动编译,并运行在本地 localhost:3000 正常情况下,浏览器会自动打开这个地址,看到React的默认页面,这样项目就算是创建完成了
完成上面的一步后,项目只能在chrome中运行和调试,如果我们想要让项目在vscode中进行调试,就得在vscode中安装相应的插件 Debugger for Chrome
接下来配置launch.json 如果你没有配置过launch.json,那你切换到vscode的调试页,看到的页面应该是这样的 点击蓝色的文字 “创建 launch.json” 文字, 选择环境Chrome,就会自动为我们创建好 .vscode/launch.json 文件 原始内容一般是这样的
{ // 使用 IntelliSense 了解相关属性。 // 悬停以查看现有属性的描述。 // 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387 "version": "0.2.0", "configurations": [ { "type": "chrome", "request": "launch", "name": "Launch Chrome against localhost", "url": "http://localhost:8080", "webRoot": "${workspaceFolder}" } ] }在项目的根目录下会出现这个文件 我们把里面的内容替换成这样
{ "version": "0.2.0", "configurations": [{ "type": "chrome", "request": "launch", "name": "Launch Chrome", "url": "http://localhost:3000", // 改为目标 url "webRoot": "${workspaceFolder}/src", "sourceMapPathOverrides": { "webpack:///src/*": "${webRoot}/*", } }] }接下来就可以用vscode进行调试了
首先还是得用 npm start 命令,让项目先运行 运行成功后,先关闭窗口这时启动vscode的调试功能 在vscdoe中按F5 或者是使用这个按钮 此时,chrome会自动打开另外一个窗口,运行我们的React项目接下来我们在项目的App.tsx文件中加入一些语句,并设置断点 刷新一下刚刚打开的浏览器页面 已经成功进入断点, 可以控制单步运行,观察变量的值等等 chrome控制台中的日志信息 vscode调试控制台中的打印出来的信息 chrome中的打印日志 和 vscode中的打印日志,功能也都正常
我们在使用vscode调试的过程中,发现原有的console.log功能比较薄弱,接下来我们就想办法稍微增强下log的功能,为它添加时间,函数,文件名和行号的功能 还有另外一个痛点,我们开发阶段经常会写很多了log语句在代码中,方便我们进行调试,但是如果项目正式上线以后,会要求把log都删除掉,以免泄露过多的信息,这时候一个一个删除显示是比较麻烦的, 所以,我们实现2个功能 1 增加log的信息 2 生产环境下自动禁用输出功能
首先安装如下2个npm包 npm install source-map-support --save npm install babel-plugin-source-map-support --save-dev并且在项目某个文件中引入 import “source-map-support/register” 这两个插件的目的是为了让代码在使用 new Error() 获取错误堆栈的时候,正确得使用sourcemap,从而得到正确的源文件名和行号,而不是打包后的文件 如果不使用这两个包,那么在new Error()中获取到的堆栈信息,是经过webpack打包压缩后的文件信息,并不会还原成原始的ts文件信息 (ps: 但是在chrome控制台中输出的堆栈信息可以正确还原)
新建一个LogHelper.ts文件,我们在这里重写console.log 我一般会把文件创建在src/utils目录下 文件内容如下 //引入source-map-support,babel-plugin-source-map-support插件 import "source-map-support/register"; import path from "path"; import moment from "moment";//好用的获取时间的包 export class LogHelper { static Init() { //重新console.log() let log = console.log; console.log = function (message: any, ...args: any[]) { //如果是生产环境下,不打印任何内容 //create-react-app 这个脚手架生产的项目, //默认情况下,生产环境下process.env.NODE_ENV = "production", //开发环境 process.env.NODE_ENV = "development" if (process.env.NODE_ENV === "production") { return; } let stackInfoStr = LogHelper.stackInfo(); //console.log()是可以控制输出内容的颜色的,这样的格式 //console.log("%c这是要打印的内容","color:blue") //这里将时间戳,行数等信息打印成不同的颜色,内容为默认的白色 let info = `%c[${moment().format("YYYY-MM-DD HH:mm:ss.SSS")}][log][${stackInfoStr.file}:${stackInfoStr.line} (${stackInfoStr.method})] %c`; log(info, "color: #48d1cc", "color: white", message, ...args); }; //重新console.info() let loginfo = console.info; console.info = function (message: any, ...args: any[]) { if (process.env.NODE_ENV === "production") { return; } let stackInfoStr = LogHelper.stackInfo(); let info = `%c[${moment().format("YYYY-MM-DD HH:mm:ss.SSS")}][info][${stackInfoStr.file}:${stackInfoStr.line} (${stackInfoStr.method})] %c`; loginfo(info, "color: #3ebe3e", "color: white", message, ...args); }; //重新console.warn() let warn = console.warn; console.warn = function (message: any, ...args: any[]) { if (process.env.NODE_ENV === "production") { return; } let stackInfoStr = LogHelper.stackInfo(); let info = `%c[${moment().format("YYYY-MM-DD HH:mm:ss.SSS")}][warn][${stackInfoStr.file}:${stackInfoStr.line} (${stackInfoStr.method})] %c`; warn(info, "color: #dbd172", "color: #dbd172", message, ...args); }; //重新console.error() let error = console.error; console.error = function (message: any, ...args: any[]) { //如果要在生产环境下仍然打印error信息,则把这里的if判断去掉 if (process.env.NODE_ENV === "production") { return; } let stackInfoStr = LogHelper.stackInfo(); //error默认就是红色,如果特意指定颜色反而会变成白色的,不知道为什么 let info = `[${moment().format("YYYY-MM-DD HH:mm:ss.SSS")}][error][${stackInfoStr.file}:${stackInfoStr.line} (${stackInfoStr.method})] `; error(info, message, ...args); }; } //通过这个函数,来获取打印内容所在的文件,函数和行号 //你可以使用下 console.log(new Error()) 来试验下,看下打印出来的内容,就是通过这个方法获取到文件信息的 static stackInfo(num: number = 0) { var stackReg = /at\s+(.*)\s+\((.*):(\d*):(\d*)\)/i; var stackReg2 = /at\s+()(.*):(\d*):(\d*)/i; var stacklist = new Error().stack.split("\n").slice(3);//获取堆栈信息,其中包含文件,函数和行号 var s = stacklist[num]; var sp = stackReg.exec(s) || stackReg2.exec(s); var data: any = {}; if (sp && sp.length === 5) { data.method = sp[1]; data.path = sp[2]; data.line = sp[3]; data.pos = sp[4]; data.file = path.basename(data.path); } return data; } }文件中我直接重写了console.log console.info console.warn console.error4个方法,如果你还有其他的打印方法需要用到,也可以这样来重写. 主要需要注意的点已经写在注释中了
在项目最开始的地方调用 LogHelper.Init() 我直接写在项目入口处 index.tsx中 然后在App.tsx中测试一下 按照之前的测试方式开始调试 这是在chrome中的打印效果 这是在vscode中的打印效果 json对象,数组等都还能够正常显示 美中不足的是 1 打印内容后面默认的调用位置只能显示我LogHelper中重新打印函数的地方,不能显示我书写console.log的实际位置,不过好在这个内容已经在打印内容的头部正确显示了. 2 在vscode的打印信息中,无法显示warn 和 error 的堆栈信息 如果有哪位小伙伴知道如何解决以上两个问题,也请告诉我一下项目正常build打包以后,默认process.env.NODE_ENV 这个变量会变成 “production”,因此在实际部署项目时,就不会再打印任何内容了