使用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进行调试了
接下来我们在项目的App.tsx文件中加入一些语句,并设置断点
刷新一下刚刚打开的浏览器页面
已经成功进入断点, 可以控制单步运行,观察变量的值等等
chrome控制台中的日志信息
vscode调试控制台中的打印出来的信息
chrome中的打印日志 和 vscode中的打印日志,功能也都正常
我们在使用vscode调试的过程中,发现原有的console.log功能比较薄弱,接下来我们就想办法稍微增强下log的功能,为它添加时间,函数,文件名和行号的功能
还有另外一个痛点,我们开发阶段经常会写很多了log语句在代码中,方便我们进行调试,但是如果项目正式上线以后,会要求把log都删除掉,以免泄露过多的信息,这时候一个一个删除显示是比较麻烦的,
所以,我们实现2个功能
1 增加log的信息
2 生产环境下自动禁用输出功能
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控制台中输出的堆栈信息可以正确还原)
//引入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个方法,如果你还有其他的打印方法需要用到,也可以这样来重写.
主要需要注意的点已经写在注释中了
项目正常build打包以后,默认process.env.NODE_ENV 这个变量会变成 “production”,因此在实际部署项目时,就不会再打印任何内容了