百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 热门文章 > 正文

前端项目线上出现紧急的bug怎么处理(抓紧收藏,能保命)

bigegpt 2024-08-30 12:32 2 浏览

前言

前端开发过程中总会遇到的重大bug情况,这是我这些年总结的希望对大家有所帮助,啊不对是一定要收藏这太关键了,关键时刻能保命

背景

在项目上线后出现严重的 bug,我们需要第一时间利用线上的环境,复现 bug,并且定位 bug的代码,在修复 bug后,做打包上线操作,并且最好尽快控制或者通知所有客户端更新程序

关键步骤

1.定位 bug

部署上线的代码,通常都是打包之后的代码,都是经过压缩处理过的,这样的代码如何进行调试定位 bug?通常有 2 种方式

  • 第 1 种,通过 source map 还原线上压缩之后的代码
  • 第 2 种,用本地的跟线上同版本的代码代理到线上的接口地址

方式 1-通过 source map

在vue-cli创建的项目当中,通过npm run build生成的文件夹dist当中,有一类文件以.map结尾,例如图

疑问-什么是 source map?

简而言之,Source map 就是一个信息文件,里面储存着压缩文件位置信息。也就是说,压缩的代码的每一个位置,所对应的压缩前的位置,具体的内容可以查看JavaScript Source Map 详解这篇文章

测试-通过source map调试代码

示例代码仓库

链接

步骤

  • 步骤 1-执行程序
  • 在仓库文件夹04_部署项目toutiao-m-server里面执行命令node app
  • 步骤 2-通过chrome浏览器,打断点调试代码

存在的问题

这种方式调试代码不推荐,因为通过打断点,在chrome浏览器中点击下一步,代码会莫名其妙跳转到不该去的地方,让调试无法正常进行

方式 2-通过服务器代理

可通过跟线上版本一样的开发环境的代码,通过服务器代理的方式,访问线上的接口的方式来定义出错的代码,这里需要多vue.config.js进行配置,例子:

module.exports = {
  devServer: {
    proxy: {
      // 当我们的本地的请求 有/api的时候,就会代理我们的请求地址向另外一个服务器发出请求
      '/api': {
        target: 'http://api-toutiao-web.itheima.net/app/', // 跨域请求线上的地址
        changeOrigin: true // 只有这个值为true的情况下 才表示开启跨域
      }
    }
  }
}

2.更新程序

定位到bug之后,除了修改完和打包好代码,并把代码部署线上,最好能主动通知客户端页面,刷新页面,这样能及时的堵上程序的漏洞,防止给公司带来损失

为了实现这种业务场景,需要在代码实现后端主动通知前端页面做刷新处理,具体的方式如下:

方式1-通过 websocket 刷新客户端

websocket是h5中新增的对象,它可以在用户的浏览器和服务器之间打开交互式通信会话。使用此API,您可以向服务器发送消息并接收事件驱动的响应,而无需通过轮询服务器的方式以获得响应,具体的内容可以查看mdn上websocket的介绍

示例代码仓库

链接

前端客户端代码

在dist/index.html中,显示内容和通过websocket连接到服务端

// 创建对象和连接到服务器
const socket = new WebSocket('ws://localhost:3000')
socket.onopen = function (event) {
	console.log('连接到服务器')
}
// 服务器通知客户端刷新页面
socket.onmessage = function (event) {
	console.log('接收到服务器的消息', event.data);
	let data = JSON.parse(event.data)
	if (data.reload) {
		// 刷新页面
		location.reload()
	}
}

前端管理端代码

dist/admin.html中,点击按钮发送请求给服务器端,刷新所用在线客户端的页面

<script src="https://cdn.bootcdn.net/ajax/libs/axios/0.24.0/axios.min.js"></script>

<body>
    <button id="btn">刷新所有客户端</button>
</body>
<script>
    document.querySelector('#btn').onclick = function () {
        // 发请求,刷新所有客户端
        axios.get('http://localhost:3000/reload')
    }
</script>

服务器端代码

app.js 后端程序代码,负责部署前端程序和提供websocket的服务器端的支持

var express = require('express');
var path = require('path');
var app = express();
var expressWs = require('express-ws')(app);
// 指定静态文件托管
app.use(express.static(path.join(__dirname, './dist')))
// 对http协议请求做处理
// 处理刷新请求
app.get('/reload', function(req, res, next){
    // 得到所有的客户端
    let clients = expressWs.getWss().clients
    clients.forEach(t=>{
        let msg = JSON.stringify({reload: true})
        // 通知所有的客户端刷新页面
        t.send(msg)
    })
    res.send({status: 200, message: '刷新成功'});
});
// 对ws协议请求做处理
app.ws('/', function(ws, req) {
  ws.on('message', function(msg) {
    console.log('接收到客户端的消息', msg)
  });
  console.log('连接到客户端');
});

app.listen(3000);

方式2-通过socket.io刷新客户端

socket.io是第三方包对websocket的封装,方便websocket的使用,更多的内容查看socket.io的官网

示例代码仓库

连接

前端客户端代码

在dist/index.html中,显示内容和通过socket.io连接到服务端

<script src="https://cdn.bootcdn.net/ajax/libs/socket.io/4.4.0/socket.io.min.js"></script>
<script>
    // 创建对象和连接到服务器
    const socket = io("ws://localhost:3000");
    socket.on("connect", () => {
        console.log('连接到服务器')
    });
    // 服务器通知客户端刷新页面
    socket.on("message", data => {
        console.log('接收到服务器的消息', event.data);
        if (data.reload) {
            // 刷新页面
            location.reload()
        }
    });
</script>

前端管理端代码

dist/admin.html中,点击按钮发送请求给服务器端,刷新所用在线客户端的页面

<script src="https://cdn.bootcdn.net/ajax/libs/axios/0.24.0/axios.min.js"></script>

<body>
    <button id="btn">刷新所有客户端</button>
</body>
<script>
    document.querySelector('#btn').onclick = function () {
        // 发请求,刷新所有客户端
        axios.get('http://localhost:3000/reload')
    }
</script>

服务器端代码

app.js 后端程序代码,负责部署前端程序和提供websocket的服务器端的支持

var express = require("express");
var path = require('path')
var { createServer } = require("http");
var { Server } = require("socket.io");

var app = express();
var httpServer = createServer(app);
var io = new Server(httpServer, {
    // 跨域的配置
    cors: {
        origin: "*",
        methods: ["GET", "POST"]
    }
});
// 指定静态文件托管
app.use(express.static(path.join(__dirname, './dist')))
// 对http协议请求做处理
// 处理刷新请求
app.get('/reload', function(req, res, next){
    // 通知所有的客户端刷新页面
    io.emit('message', {reload: true});
    res.send({status: 200, message: '刷新成功'});
});
// 对ws协议请求做处理
io.on("connection", (socket) => {
    socket.on('message', function(msg) {
        console.log('接收到客户端的消息', msg)
    });
    console.log('连接到客户端');
});
// 监听3000端口,运行程序
httpServer.listen(3000);


相关推荐

Java 泛型大揭秘:类型参数、通配符与最佳实践

引言在编程世界中,代码的可重用性和可维护性是至关重要的。为了实现这些目标,Java5引入了一种名为泛型(Generics)的强大功能。本文将详细介绍Java泛型的概念、优势和局限性,以及如何在...

K8s 的标签与选择器:流畅运维的秘诀

在Kubernetes的世界里,**标签(Label)和选择器(Selector)**并不是最炫酷的技术,但却是贯穿整个集群管理与运维流程的核心机制。正是它们让复杂的资源调度、查询、自动化运维变得...

哈希Hash算法:原理、应用(哈希算法 知乎)

原作者:Linux教程,原文地址:「链接」什么是哈希算法?哈希算法(HashAlgorithm),又称为散列算法或杂凑算法,是一种将任意长度的数据输入转换为固定长度输出值的数学函数。其输出结果通常被...

C#学习:基于LLM的简历评估程序(c# 简历)

前言在pocketflow的例子中看到了一个基于LLM的简历评估程序的例子,感觉还挺好玩的,为了练习一下C#,我最近使用C#重写了一个。准备不同的简历:image-20250528183949844查...

55顺位,砍41+14+3!季后赛也成得分王,难道他也是一名球星?

雷霆队最不可思议的新星:一个55号秀的疯狂逆袭!你是不是也觉得NBA最底层的55号秀,就只能当饮水机管理员?今年的55号秀阿龙·威金斯恐怕要打破你的认知了!常规赛阶段,这位二轮秀就像开了窍的天才,直接...

5分钟读懂C#字典对象(c# 字典获取值)

什么是字典对象在C#中,使用Dictionary类来管理由键值对组成的集合,这类集合被称为字典。字典最大的特点就是能够根据键来快速查找集合中的值,其键的定义不能重复,具有唯一性,相当于数组索引值,字典...

c#窗体传值(c# 跨窗体传递数据)

在WinForm编程中我们经常需要进行俩个窗体间的传值。下面我给出了两种方法,来实现传值一、在输入数据的界面中定义一个属性,供接受数据的窗体使用1、子窗体usingSystem;usingSyst...

C#入门篇章—委托(c#委托的理解)

C#委托1.委托的定义和使用委托的作用:如果要把方法作为函数来进行传递的话,就要用到委托。委托是一个类型,这个类型可以赋值一个方法的引用。C#的委托通过delegate关键字来声明。声明委托的...

C#.NET in、out、ref详解(c#.net framework)

简介在C#中,in、ref和out是用于修改方法参数传递方式的关键字,它们决定了参数是按值传递还是按引用传递,以及参数是否必须在传递前初始化。基本语义对比修饰符传递方式可读写性必须初始化调用...

C#广义表(广义表headtail)

在C#中,广义表(GeneralizedList)是一种特殊的数据结构,它是线性表的推广。广义表可以包含单个元素(称为原子),也可以包含另一个广义表(称为子表)。以下是一个简单的C#广义表示例代...

「C#.NET 拾遗补漏」04:你必须知道的反射

阅读本文大概需要3分钟。通常,反射用于动态获取对象的类型、属性和方法等信息。今天带你玩转反射,来汇总一下反射的各种常见操作,捡漏看看有没有你不知道的。获取类型的成员Type类的GetMembe...

C#启动外部程序的问题(c#怎么启动)

IT&OT的深度融合是智能制造的基石。本公众号将聚焦于PLC编程与上位机开发。除理论知识外,也会结合我们团队在开发过程中遇到的具体问题介绍一些项目经验。在使用C#开发上位机时,有时会需要启动外部的一些...

全网最狠C#面试拷问:这20道题没答出来,别说你懂.NET!

在竞争激烈的C#开发岗位求职过程中,面试是必经的一道关卡。而一场高质量的面试,不仅能筛选出真正掌握C#和.NET技术精髓的人才,也能让求职者对自身技术水平有更清晰的认知。今天,就为大家精心准备了20道...

C#匿名方法(c#匿名方法与匿名类)

C#中的匿名方法是一种没有名称只有主体的方法,它提供了一种传递代码块作为委托参数的技术。以下是关于C#匿名方法的一些重要特点和用法:特点省略参数列表:使用匿名方法可省略参数列表,这意味着匿名方法...

C# Windows窗体(.Net Framework)知识总结

Windows窗体可大致分为Form窗体和MDI窗体,Form窗体没什么好细说的,知识点总结都在思维导图里面了,下文将围绕MDI窗体来讲述。MDI(MultipleDocumentInterfac...