搅动了dotnet3.1 + vue2.6的屎山代码,我先吃了!

如果领导要你改一个无人维护的四年前的项目,而且您完全不熟悉语法,如何应对?

总算是把这坨屎部分消化了…… ——kerman

故事的起因

很简单,我司接到了一个项目,需要修改 Z 系统,然后再收一笔钱……就是这样。那么有什么问题呢?

问题就是👇:

  1. Z 系统是四年前由不知道谁开发的(那几个人已经跑路了)。
  2. Z 系统的源码和现在生产环境的并不一样。
  3. Z 系统用到了先进的c#(.net3.1) + vue2,好巧不巧这俩我都没碰过。

😔还能咋办嘛。钱难挣屎难吃,要生活嘞嘛……挨个解决呗。解决方案嘛,就……发挥自己的主观能动性呗。

当时的开发人员跑路了

笑死🤣这是对领导来说最简单的问题了。上一批跑路了,你(指我)来改不就行了。

好,问题1解决。

Z 系统的源码不是最新的

准确的说,我夸张了。其实c#的代码是新的,只不过vue2的代码是老旧的。

老旧到什么程度呢?也就几乎不可用的状态吧。

那还不是得改啊,还能怎么办,反正代码和我总要跑一个。但是我现在不好跑……

两个方案👇

  1. 我凭着感觉,在老旧的代码上修修补补。
  2. 找当时的开发人员要一份代码库😅

一目了然,方案一就不是我这种混子干的事儿。方案二呢,不知道领导出于何种考虑,也放弃了。然后领导给出了方案三:反编译vue2代码。

我承认,我年纪轻,我涉猎不广泛,我愣住了。但是还是得答应下来啊,要吃饭的嘛……但是你说好巧不巧,vue2这坨老东西,还真给我留了一线生机。(说白了就是vue2默认打包会存在源码泄露的问题😓)

可以参考这篇文章,以及我和chatgpt的一些对话👇

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
`.js.map` 文件(即 Source Map)的时候,**反编译 Vue 2 项目时可以非常接近开发时的源码**,但仍存在一些**细微偏差**,以下是详细解释:

---

### ✅ 有 `.js.map` 的情况下,可以得到什么:

Source Map 文件的作用是将**编译/打包后的代码**映射回**原始源码(通常是 ES6+、TypeScript、SFC 等)的位置**。有了它:

1. **还原出的 JavaScript 结构和逻辑接近原始代码**,变量名、函数名、模块结构基本一致。
2. **Vue 单文件组件(.vue 文件)可被还原为 JS、模板、样式三部分的拼接结构**
3. 使用如 [source-map-explorer](https://www.npmjs.com/package/source-map-explorer)、\[webpack-bundle-analyzer] 或 DevTools 都可以对照还原源码。

---

### ⚠️ 仍然可能存在的偏差:

| 项目 | 偏差原因 | 举例说明 |
| ------ | ------------------------------------- | ------------------------------------------ |
| 注释、空行 | 编译时通常被删除 | 代码中不会还原开发时的注释说明 |
| 文件结构 | webpack 打包时可能将多个模块合并 | 不容易看出模块物理位置(路径) |
| 模板还原 | `.vue` 文件的 template 部分编译成渲染函数 | 难以100%还原 SFC 中的 HTML 模板原貌 |
| 样式处理 | 使用了 CSS Modules、预处理器如 SCSS | 还原的样式可能丢失原变量、嵌套关系 |
| 命名略有变化 | 如开启了 scope 或 minify(但有 map 文件可以恢复大部分) | 比如变量从 `let userInfo` 变成 `let a`,但有 map 会还原 |

---

### 🔐 开发者如何保护源代码?

如果不希望源码被轻易还原,常见做法包括:

* 发布前 **不生成或不发布 `.js.map` 文件**
* 开启 **代码混淆、压缩**
* 使用 Vue3 并结合 WebAssembly 或后端渲染

---

### ✅ 总结:

`.js.map` 文件时,**反编译结果和开发源码高度接近,接近源码泄露的程度**,尤其是 JS 逻辑。如果要保护源码,发布时务必**去掉 `.map` 文件**

显而易见的,当时的那几个兄弟直接默认就把 *.js.map文件放到了生产环境,我又可以操作了。接下来就是按照文档教程,拿到反编译后的文件就行了。

嗷顺便说一句,他们当时的打包方式是,两个vue2项目的dist文件夹直接合并,并修改index.html文件名。nb,我还得根据更新时间手动分开两套源码。

c#和vue2我不会呀

vue2还好,从vue3切到vue2,我个人的直观理解就是从组合式api切换到了选项式api,至于其他的细节,我也用不到。

那么c#咋办?我一个java都懒得用的人,看到c#真是一头大。欸,别急,我先别急,领导发力了。领导说他来改c#。好,妙!那我自然要衬托出领导的英明神武,配合即可。然后嘛,就是解决代码层面的问题。

其实改改前端也没有啥大的问题,原项目用的是ant-design-vue,直接对着文档来,也算是顺手,改前端的时候也没遇到什么大问题,只不过搅动了屎山,肯定要再拉一坨,不然对不起我自己。


就比如把,原项目请求数据用的是 axios 二次封装的。好好好,你封装得很好,但是我不会看。已有的功能我不碰,新的功能我直接用fetch,写在.vue里面,主打一个不给后来人(有可能是我自己)留后路。想改?好哇,您慢慢排查去吧!

嗷更新一下,其实也不是故意的,就是单纯的不想看他封装的东西,觉得用fetch顺手一些,虽然后来我也按照他的思路和代码层级重新写了。


另一个大的问题就是,环境……

联调的时候,dotnet3.1还好,微软的包维护得还是可以的。但是node这边,一言难尽。当时那几兄弟用的taobao.org的镜像源,现在已经失效了。哎,只有一个一个排查,慢慢npm install试咯!、


他妈的还有一个问题,他们遗留了一些错误代码,而且我又太相信他们了,导致走了一点弯路。
给各位看看他们的代码嗷!👇

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/**axios封装
* 请求拦截、相应拦截、错误统一处理
*/
import axios from 'axios';
import {mutations, store} from '../store';

export const TIP = "http://127.0.0.1:5000";
export const fileApi = TIP + "/api/Resourcess/UploadImg?token=" + store.token; //上传文件
export const ReadFileApi = TIP + "/api/Resourcess/Read/Read"; //获取图片
export const ReadVideoApi = TIP + "/api/foreground/Video/Play"; // 获取视频资源

// 环境的切换
if (process.env.NODE_ENV == 'development') {
axios.defaults.baseURL = TIP;
} else if (process.env.NODE_ENV == 'debug') {
axios.defaults.baseURL = '';
} else if (process.env.NODE_ENV == 'production') {
axios.defaults.baseURL = '';
}

我是那么的相信他们,看他们生产环境和开发环境配置有做分离,直接npm build就丢到服务器上了,结果资源定位还是127.0.0.1。
嗷,结果他妈的回头一看,他妈的环境的切换,切换了个锤子,他妈的几个Api都写死成127.0.0.1了,人才!我看他们的git记录(本地的)还是几个人协作的,我都不知道他们协作了个啥子。

故事的最后

就是把几个功能改改,界面修修,然后重新打包放上去了。其实要说很难吗?感觉也不难,就是觉得碰别人的屎山代码很难受,很难受。告一段落后的我随便写点东西来吐槽一下罢了。

差不多该下班了,溜溜球。