【在开发小程序的时候如何排查问题】

news2024/11/25 11:22:52

在开发小程序的时候如何排查问题

在最近开发小程序的时候,经常出现本地在浏览器中调试没有问题,但是一发布到预发环境就出现各种个样的问题

  1. 手机兼用性问题

    有时候会出现苹果🍎手机键盘弹出,导致ui界面高度出现异常
    
  2. 边界问题,导致js报错

    小程序页面出现白屏,可能是js报错,但是我们没办法像在浏览器中一样去打开控制台查看日志报错信息
    但是自己本地又复现不了
    
  3. 后端接口报错

 有时候新增/修改调用后端接口的时候,后端接口可能会对字段进行校验,抛出错误信息,
 说你某个字段传递的有问提,但是我们无法真正捕获到有用的信息,比如这个字段传递给后端的时候到底是怎样的,
 有时候不得不麻烦后端同学去查看一下后端接口的日志信息,每次这样去找后端,也是会被讨厌的不是吗。

所以,作为前端的小伙伴我们应该怎样处解决小程序开发中所出现的问题呢?

我们这边以react开发小程序为例

  1. 面对js报错问题,我们可以开发一下 ErrorBoundary 组件,在组件内部捕获js报错,并在页面上展示错误信息
    不管是在开发环境还是在生产环境,这个组件都能很好的帮助开发者排查前端问题。

ErrorBoundary 原理使用 react 类组件中的 componentDidCatch生命周期 进行错误的捕获,如果有错误信息则展示错误信息否则展示正常的页面

  
import React from "react";
import styles from "./index.less";
import { Toast } from "antd-mobile";

class ErrorBoundary extends React.Component<any,{ hasError: boolean; errorInfo: string }> {
  constructor(props) {
    super(props);
    this.state = { hasError: false, errorInfo: null };
  }

  static getDerivedStateFromError(error) {
    // 更新状态使得下一次渲染能够显示降级后的UI
    return { hasError: true };
  }

  componentDidCatch(error, errorInfo) {
    // 你同样可以将错误日志上报给服务器
    const url = location.href;
    this.setState({ errorInfo: `${error.toString()}\n当前地址:${url}` });
  }

  render() {
    /* 复制去反馈 */
    const onCopy = () => {
      navigator.clipboard.writeText(this.state.errorInfo);
      Toast.show({
        content: "复制成功",
      });
    };

    if (this.state.hasError) {
      // 你可以渲染任何自定义的降级UI
      return (
        <div className={styles.errorBoundary}>
          <h2>哦呦,出错啦</h2>
          <p>{this.state.errorInfo}</p>
          <div onClick={onCopy} className={styles.errorBoundaryFooter}>
            复制去反馈
          </div>
        </div>
      );
    }

    return this.props.children;
  }
}

export default ErrorBoundary;

ps: 样式可以自行定义
  1. 我们有时候前端打印了很多日志,想去排产问题或者查看数据格式,但是我们无法在浏览器中打开控制台查看,我们怎么去排查呢?
不推荐,但是可用

思路:实现一个react组件,该组件可以配置在最外层,则他的子组件里的所有原生的console方法,都会被重写,重写的console方法会自动收集打印的日志内容,并将内容存储起来,然后在ui中呈现出来

实现结果

//index.jsx
 import React, { createContext, useContext, useState, useEffect } from "react";

// 创建一个日志上下文
const LogContext = createContext(null);

// 创建一个高阶组件来提供日志收集功能
export const LogProvider = ({ children }: any) => {
  const [logs, setLogs] = useState([]);
  console.log(logs, "logs");
  // 存储原生 console 方法
  const consoleMethods = {} as any;

  useEffect(() => {
    // 重写 console 方法
    Object.keys(console).forEach((method: any) => {
      if (typeof console[method] === "function") {
        consoleMethods[method] = console[method];

        console[method] = (...args) => {
          /* 阻止打印日志logs的时候添加到集合中 */
          if (!args.toString().includes("logs") && logs?.length <= 100) {
            setLogs((prevLogs) => [...prevLogs, { method, args }]);
          }
          consoleMethods[method](...args);
        };
      }
    });

    // 清理函数,恢复原生 console 方法
    return () => {
      Object.keys(console).forEach((method) => {
        if (consoleMethods[method]) {
          console[method] = consoleMethods[method];
        }
      });
    };
  }, []);

  // 提供日志和日志收集状态
  return (
    <LogContext.Provider value={{ logs, setLogs }}>
      {children}
    </LogContext.Provider>
  );
};

// 创建一个自定义 Hook 来访问日志上下文(可选)
export const useLogs = () => useContext(LogContext);

//  LogViewer.jsx
import React from "react";
import { useLogs } from "./index"; // 请根据实际文件路径调整
import _ from "lodash";
import JsonView from "react18-json-view";
import "react18-json-view/src/style.css";
import RedBox from "redbox-react";

const LogViewer = () => {
  const { logs } = useLogs();
  return (
    <div>
      <h3>Log Viewer</h3>
      <ul
        style={{
          maxHeight: "300px",
          overflowY: "scroll",
          background: "#f0f0f0",
          padding: "1rem",
          border: "1px solid #ddd",
        }}
      >
        {logs.map((log: any, index: any) => (
          <li key={index}>
            <strong>{log.method}</strong>:{" "}
            {log.args.map((arg: any) => {
              if (_.isObject(arg)) {
                return <JsonView src={arg} />;
              } else {
                return arg.toString();
              }
            })}
          </li>
        ))}
      </ul>
    </div>
  );
};

export default LogViewer;

使用方式

// 在最外层使用
import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App.tsx";
import { LogProvider } from "./components/LogTools/index.tsx";
import LogViewer from "./components/LogTools/LogViewer.tsx";
import "./index.css";

ReactDOM.createRoot(document.getElementById("root") as HTMLElement).render(
  <React.StrictMode>
    <LogProvider>
      <LogViewer />
      <App />
    </LogProvider>
  </React.StrictMode>
);

ps: 最好做一个悬浮的工具按钮,让其悬浮固定在页面某个位置,点击查看日志即可

  1. 如何收集查看日志/网络请求等关键信息,当然也可以重新二次封装我们的请求,但是这件事请已经有人帮我们做了有一个公共的npm库
    Mdebug
    安装: npm install --save-dev mdebug 测试环境/预发环境使用、别上生产环境
    使用: 在我们的项目主文件中main.tsx中直接引用即可
import mdebug from "mdebug";
mdebug.init();

效果图:
img

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1952927.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

for循环打印1~10之间数字

对于for循环之前了解不够的同学可以看之前的我写的介绍 我们这里直接上代码 #include<stdio.h> int main() {int i 0;for (i 1; i < 11; i){printf("%d\n", i);}return 0; }

0724_驱动1 字符设备驱动内部实现

一、字符设备驱动内部实现工作原理 二、分布实现字符设备驱动API接口 分配对象&#xff1a; #include <linux/cdev.h> struct cdev *cdev_alloc(void) 函数功能&#xff1a;分配对象struct cdev *结构体指针 参数&#xff1a;无 返回值&#xff1a;成功返回struct cdev *…

人工智能类——计算机科学与技术

计算机科学与技术是一个非常大的门类。目前计算机科学与技术类招生的专业主要有计算机科学与技术、软件工程、网络工程、信息安全、物联网工程等&#xff0c;后面的几个专业是计算机科学与技术的重要分支&#xff0c;而这个门类的其他分支并没有单列出来一个本科专业&#xff0…

实战|EDU挖掘记录-某学校sql注入挖掘记录

本文来源无问社区&#xff0c;更多实战内容&#xff0c;渗透思路尽在无问社区http://www.wwlib.cn/index.php/artread/artid/9755.html 某大学的办公系统&#xff0c;学号是我从官网下载的优秀人员名单找到的&#xff0c;初始密码为姓名首字母加身份证后六位&#xff0c;我是社…

高级及架构师高频面试题-基础型

1、设计模式有哪些原则&#xff08;待解释的更直白&#xff09; 单一职责原则&#xff1a;一个类或方法应只负责一项职责&#xff0c;避免一个类因为多个变化原因而改变。开闭原则&#xff1a;软件实体应对扩展开放&#xff0c;对修改封闭。比如要增加用户类别的时候可以新增一…

Java高频面试题分享

文章目录 1. 策略模式怎么控制策略的选取1.1 追问&#xff1a;如果有100种策略呢&#xff1f;1.2 追问&#xff1a;什么情况下初始化Map 2. 什么是索引&#xff1f;什么时候用索引&#xff1f;2.1 追问&#xff1a;怎么判断系统什么时候用量比较少2.2 追问&#xff1a;如何实时…

树 ----- 基础学习

树 树&#xff1a;n&#xff08;n>0&#xff09;个结点的有限集合。n 0 ,空树。 在任意一个非空树中&#xff0c; 1&#xff0c;有且仅有一个特定的根结点 2&#xff0c;当n>1 时&#xff0c;其余结点可分为m个互不相交的有限集合T1,T2,T3.。。。。Tm&#xff0c;其中每…

使用 uPlot 在 Vue 中创建交互式图表

本文由ScriptEcho平台提供技术支持 项目地址&#xff1a;传送门 使用 uPlot 在 Vue 中创建交互式图表 应用场景介绍 uPlot 是一个轻量级、高性能的图表库&#xff0c;适用于创建各种交互式图表。它具有丰富的功能&#xff0c;包括可自定义的轴、网格、刻度和交互性。本篇博…

脊髓损伤的小伙伴锻炼贴士

Hey小伙伴们~&#x1f44b; 今天要跟大家聊一个超燃又超温馨的话题&#xff01;&#x1f31f; 对于我们脊髓损伤的小伙伴们来说&#xff0c;保持身体活力&#xff0c;不仅是健康的小秘诀&#xff0c;更是拥抱美好生活的超能量哦&#xff01;&#x1f4aa; #脊髓损伤# 首先&…

【ffmpeg命令入门】Nginx的安装与制作HLS流媒体服务器

文章目录 前言Nginx简介Ubuntu安装Nginxffmpeg生成HLS流媒体1. 生成HLS流媒体命令说明 配置Nginxffplay播放m3u8 总结 前言 在数字内容传输和流媒体服务中&#xff0c;HLS&#xff08;HTTP Live Streaming&#xff09;已经成为一种流行的解决方案&#xff0c;特别是在视频直播…

FPGA FIFO IP核(2)- 配置与调用

前言 上上期介绍了FIFO IP核理论方面的一些内容&#xff0c;接下来开始进行FIFO IP核的配置和使用部分。 FIFO IP核再理解 关键点 先进先出&#xff1a;数据按顺序写入FIFO&#xff0c;先被写入的数据在读取的时候先被读出。 FIFO存储器没有地址线。 FIFO主要作为缓存&#…

C语言 | Leetcode C语言题解之第275题H指数II

题目&#xff1a; 题解&#xff1a; int hIndex(int* citations, int citationsSize) {int left 0, right citationsSize - 1;while (left < right) {int mid left (right - left) / 2;if (citations[mid] > citationsSize - mid) {right mid - 1;} else {left mi…

时效性知识点是否值得花时间学习和研究

新趋势 智能大模型训练成本与人才培养成本之间的博弈。 视频 录了个断断续续的视频&#xff1a; 编程简单吗&#xff1f;为什么技术型内容几乎停更了&#xff1f; 代码形式的程序 /** Created by ArduinoGetStarted.com** This example code is in the public domain** Tuto…

[算法]插入排序和希尔排序

这里简单的介绍一下插入排序和希尔排序的算法实现&#xff0c;为简单起见&#xff0c;排序为升序且排序的数组是整形数组。 一、插入排序 &#xff08;一&#xff09;、算法思路 把数组里的第一个元素视为有序的&#xff0c;然后取第二个元素与前面的元素作比较&#xff0c;如…

2024钉钉杯A题思路详解

文章目录 一、问题一1.1 问题1.2 模型1.3 目标1.4 思路1.4.1 样本探究1.4.2 数据集特性探究&#xff1a;1.4.3 数据预处理1.4.4 数据趋势可视化1.4.5 ARIMA和LSTM两种预测模型1.4.6 参数调整 二、问题二2.1 问题2.2 模型2.3 目标2.4 思路2.4.1 样本探究2.4.2 数据集特性探究2.4…

jenkins中shell脚本中使用构建参数化Groovy变量的四种方式

jenkins中shell脚本中使用构建参数化Groovy变量的四种方式: 以字符变量为例&#xff1a; 流水线代码&#xff1a; pipeline {agent {//label "${server}"label "${28}"}stages {stage(Hello) {steps {echo Hello Worldecho "${28}"echo "…

C语言-TCP通信创建流程

TCP通信创建流程 1. 客户端创建TCP连接 在整个流程中, 主要涉及以下⼏个接⼝socket() : 创建套接字, 使⽤的套接字类型为流式套接字connect() : 连接服务器send() : 数据发送recv() : 数据接收创建套接字 首先&#xff0c;我们需要创建套接字&#xff0c;套接字是通信的基础…

Adobe Lightroom Classic 2024(LRC2024)软件下载(附下载链接)+LRC教程

目录 一、简介 二、下载 三、功能 四、使用操作 一、简介 Adobe Lightroom Classic 2024&#xff08;简称LRC2024&#xff09;是Adobe公司推出的一款专业级照片处理和管理软件&#xff0c;广泛应用于摄影师和摄影爱好者中。作为Adobe家族的一员&#xff0c;LRC2024在继承前…

平价不入耳运动耳机哪款最好?五款回购榜优品种草

许多有健身运动习惯的朋友在选择耳机时会优先考虑不入耳耳机&#xff0c;因为它佩戴舒适&#xff0c;稳固性和安全性更高&#xff0c;不仅在运动时不会轻易掉落&#xff0c;还能够方便我们在进行户外运动时接收外界的声音。那么&#xff0c;平价不入耳运动耳机哪款最好&#xf…

Spark实时(一):StructuredStreaming 介绍

文章目录 Structured Streaming 介绍 一、SparkStreaming实时数据处理痛点 1、复杂的编程模式 2、SparkStreaming处理实时数据只支持Processing Time 3、微批处理,延迟高 4、精准消费一次问题 二、StructuredStreaming架构与场景应用 三、​​​​​​​​​​​​​​…