灏天阁

线上崩了?一招教你快速定位问题!

· Yin灏

👏 背景

本文是 从零到亿系统性的建立前端构建知识体系 ✨ 中的第七篇。

image.png

正浏览着下班后去哪家店撸串,结果隔壁组同事囧着脸过来问我:大哥,赶紧过去帮忙看个问题!客户反馈很多次了,一直找不出问题出在哪里!!!

我:能不能有点周五的样子!你小子耽误我下班啊!!

582a3535-38fb-42d2-8178-2b16bb26e7a5.jpg

过去简单的了解一下,据说是个历史遗留问题,极难复现!

  • 后端同学:数据绝对没问题,都仔细校对过了!😳😳
  • 前端同学:线上报错信息啥也看不出来,我本地是好的!要不你们再试试?🤔🤔
  • 测试同学:复现纯靠缘分!😰😰

image.png

我:这么说看来是有鬼了,要不你们在座位上摆个香炉烧根香?

136edee9-e196-4e09-9e71-41792ff993f4.jpg

坐下后我一顿操作猛如虎,五分钟后就定位出了问题,老板在知晓这件事后:

image.png

😥 背后原因分析

思考这背后的原因,根本在于是大家不知道怎么调试线上问题,都是靠猜。猜对了皆大欢喜,猜错了换个方向继续猜,直到陷入怀疑自我的情绪中……

image.png

今天借此机会,我决定祭出独门绝技,教大家一招 bug 定位消失术!彻底摆脱线上问题恐惧症!

说回正题

线上问题大致可以分两类:一类是接口数据导致的另一类是数据正常,前端哪里疏忽了导致的

  • 数据不同:本地更多的是用的测试环境的数据,而线上用的真实环境的数据。不同数据,页面的渲染以及交互可能不同;
  • 代码疏忽:可能是某些场景的边界情况没有处理好,再或者是未做容错降级处理等;

💁 模拟线上环境

文中所涉及到的代码均放到个人 github 仓库中:github.com/noBaldAaa/o…

通过 create-react-app 初始化一个项目(你也可以用 vue-cli,都一样):

npx create-react-app my-app --template typescript

接着在控制台运行 yarn eject,把 Webpack 的配置暴露出来(用其他构建工具也一样,这里以 Webpack 为例),此时项目目录结构:

├── build # 打包后的文件夹
├── config # webpack配置信息
|    └── webpack.config.js
├── node_modules
├── public
├── package-lock.json
├── package.json
└── src # 源码目录
     └── index.tsx

index.tsx 中写一段错误的代码模拟报错:

import React, { useEffect } from "react";
import ReactDOM from "react-dom/client";

function App() {
  const obj: any = {
    author: "不要秃头啊",
  };
  useEffect(() => {
    //报错代码在这里!!!!!!!!!!!
    obj.abc.map((item: any) => item === "1111");
  });
  return (
    <div className="App">
      <h1>hello world</h1>
    </div>
  );
}

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

模拟生产环境打包,修改 config/webpack.config.js 中的配置:

   mode: "production",
   devtool: false,
  • mode: "production" 表示采用生产模式打包,会启用代码压缩等插件
  • devtool: false 表示不生成 source-map文件

接着在控制台运行 yarn build 命令,生成打包后的文件:/build

image.png

为了模拟线上,这里用一个第三方库:http-server,根据官方介绍:它是是一个简单的、零配置的命令行静态 HTTP 服务器。下面是官方介绍图,确实挺形象……

image.png

该说不说,确实很简单,这点没吹牛比 👍,一行代码就可以起一个静态的 HTTP 服务器:

npx http-server ./build

image.png

点击静态服务器地址,打开页面发现确实报错了:

image.png

所有代码都被压缩成了一行,确实啥都看不出来。

image.png

💣 小型必杀技

上面我们提到,本地没问题,线上有问题,一部分原因就是因为后端数据有问题,这里先祭出一个小型必杀技:Ajax Interceptor

它是一个谷歌插件,可以拦截页面上的 Ajax 请求,并把返回结果替换成任意文本。这对  mock 数据、排查线上问题 来说简直就是神器!!!

Charles 等抓包软在它面前就是个弟弟(我没有侮辱 Charles 的意思,大家各有长处)。当我知道了这个插件之后,才发现以前的操作都花里胡哨的!!!

f74cd6c8-40af-491f-981d-573d7c892b0a.jpg

示范一下,把我的掘金等级改成 8 级,掘力值和关注者加几个 999,这不过分吧!

image.png

此处 @掘金运营 @优弧,叫你们开发来改 bug 啦,这小子数据已经爆表了。

使用方式:

(1)点击插件图标

按钮.png

(2)把你想要修改的接口 URL 地址复制到输入框中,然后把返回的内容放到下面的文本框

操作界面.png

拍了个视频教程:

vgfmk-jxiy4.gif

友情提示:不需要用的时候别忘记关掉!!!要不然有可能分析半天,最后发现忘关插件了……

image.png

🚀 终极必杀技

上面那个小工具可以解决大部分场景的问题,但万一不是后端数据的问题,是我们自己的问题呢? image.png

这个时候再说:我本地是好的,你再试试?

此时老板要拿刀过来了……

回归本质,线上不能定位到问题的原因是什么?不就是因为生产环境没有生成和上传 source-map 文件吗!!

那我们直接给线上环境添加上 source-map 文件不就可以了吗?

a2a20c88-c702-45d2-8fea-972dda3872eb.jpg

部分心急的同学请你把刀放下,我并不是说在生产环境上传 source-map 文件。

我的意思是:生产环境 + 本地的 source-map 文件

这里偷偷告诉大家一个小秘密(99%的人都不知道,勿外传):谷歌浏览器的 Sources 面板支持右键添加 source-map

image.png

有了方案后,现在只需把生产环境的代码按照如下配置在本地重新打包:

output: {
  path: path.resolve(__dirname, "build2");
} //原build文件夹在模拟线上环境,这里改成build2防止影响之前的服务
devtool: "source-map";;

然后用 http-server 起一个静态服务:

npx http-server ./build2

拿到 source-map 的文件链接添加到浏览器中:

image.png

操作视频:

elwna-z6ibd.gif

这是添加前的效果:

image.png

这是添加后的效果:

image.png

堆栈信息一目了然,一下就能看到是哪个文件下的哪行代码出了问题!

image.png

👋 总结

本文从一个团队小故事出发,详细讲述了当前端开发者遇到线上问题时的囧境。从以下两个场景剖析,给出了对应的解决方案:

  • 数据不同导致出错:在本地环境下使用 Ajax Interceptor 来模拟线上数据;
  • 代码疏忽导致出错:直接在线上环境添加 source-map 链接来定位问题;

什么?这两个方案还不够?这已经是我知道的最简单的方式啦!!我已经把我知道的全说了 😭😭😭

什么?你们项目里集成了 sentry 等监控系统?那就当我没说!我闭嘴了!

什么?……

引用:

推荐阅读

  1. 从零到亿系统性的建立前端构建知识体系 ✨
  2. 我是如何带领团队从零到一建立前端规范的?🎉🎉🎉
  3. 【Webpack Plugin】写了个插件跟喜欢的女生表白,结果……😭😭😭
  4. 前端工程化基石 – AST(抽象语法树)以及 AST 的广泛应用 🔥
  5. 学会这些自定义 hooks,让你摸鱼时间再翻一倍 🐟🐟
  6. 浅析前端异常及降级处理
  7. 前端重新部署后,领导跟我说页面崩溃了…
  8. 前端场景下的搜索框,你真的理解了吗?
  9. 手把手教你实现 React 数据持久化机制
  10. 面试官:你确定多窗口之间 sessionStorage 不能共享状态吗???🤔

- Book Lists -