Files
integral-resell/h5/static/js/chunk-vendors.4d47960d.ANALYSIS.md

714 lines
17 KiB
Markdown
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# chunk-vendors.4d47960d.js 详细分析
## 文件信息
- **文件名**: chunk-vendors.4d47960d.js
- **大小**: 1.18MB (1,181,721 bytes)
- **类型**: Webpack第三方依赖打包文件
- **压缩**: 高度压缩约26行
- **模块数**: 约200+个模块
## 文件用途
这是Webpack打包的第三方依赖库文件包含应用所需的所有外部库和polyfills。主要包括
- uni-simple-router完整路由库
- 加密库HMAC, SHA, MD5等
- Buffer实现
- 各种Polyfills
---
## 主要库分类
### 1. uni-simple-router 路由库
这是核心依赖,占据了大部分代码量。
#### 核心模块
| 模块ID | 名称 | 功能 |
|--------|------|------|
| **607** | 主入口 | 导出createRouter, RouterMount等 |
| **366** | 常量定义 | hookToggle, navtypeToggle等 |
| **309** | 类型定义 | TypeScript类型声明 |
| **169** | 钩子调用 | loopCallHook, transitionTo等 |
| **890** | 导航跳转 | navjump, lockNavjump, createRoute |
| **845** | 页面钩子 | proxyPageHook, createFullPath |
| **99** | 查询参数 | queryPageToMap, parseQuery |
| **314** | 方法重写 | rewriteMethod |
| **963** | 路由创建 | createRouter, RouterMount |
| **809** | 原生跳转 | uniOriginJump |
| **662** | 钩子注册 | registerEachHooks |
| **460** | Mixins | initMixins, getMixins |
| **789** | 工具函数 | deepClone, getDataType等 |
| **883** | 日志工具 | err, warn, log |
| **282** | 配置常量 | baseConfig, proxyHookName |
| **801** | 路由映射 | createRouteMap |
| **814** | 加载页面 | registerLoddingPage |
| **334** | 路径获取 | getEnterPath |
| **779** | 路径匹配 | pathToRegexp |
#### 功能详解
##### 路由创建 (模块 963)
```javascript
function createRouter(options) {
return {
// 配置
options,
mount: [],
Vue: null,
routesMap: {},
// 导航方法
push(location) { ... },
replace(location) { ... },
replaceAll(location) { ... },
pushTab(location) { ... },
back(delta, options) { ... },
// 守卫
beforeEach(fn) { ... },
afterEach(fn) { ... },
// 安装
install(Vue) { ... }
};
}
```
##### 导航跳转 (模块 890)
```javascript
// 核心导航函数
function navjump(rule, router, NAVTYPE, forceNav, uniActualData, callback, passthrough) {
// 1. 处理back类型
if (NAVTYPE === "back") {
// 构建返回参数
}
// 2. 解析路由
var query = queryPageToMap(rule, router).rule;
query.type = navtypeToggle[NAVTYPE];
// 3. 处理params到query
var finalRule = paramsToQuery(router, query);
var resolvedRule = resolveQuery(finalRule, router);
// 4. H5平台特殊处理
if (router.options.platform === "h5") {
if (NAVTYPE !== "push") NAVTYPE = "replace";
if (forceNav != null) {
forceNav.next({ replace: NAVTYPE !== "push", ...resolvedRule });
} else {
router.$route[NAVTYPE](resolvedRule);
}
}
// 5. 小程序/App平台
else {
// 创建to和from
var to = createToFrom(resolvedRule, router);
var from = getCurrentRoute(router);
createFullPath(resolvedRule, from);
if (!passthrough) {
return resolvedRule;
}
// 触发守卫
transitionTo(router, resolvedRule, from, NAVTYPE, HOOKLIST, function(next) {
uni[navtypeToggle[NAVTYPE]](resolvedRule, true, next, callback);
});
}
}
// 带锁的导航
function lockNavjump(rule, router, NAVTYPE, forceNav, uniActualData) {
lockDetectWarn(router, rule, NAVTYPE, function() {
// H5不锁定
if (router.options.platform !== "h5") {
router.$lockStatus = true;
}
navjump(rule, router, NAVTYPE, void 0, forceNav, uniActualData);
}, uniActualData);
}
```
##### 路由守卫 (模块 169)
```javascript
// 守卫钩子列表
var HOOKLIST = [
// 1. 全局前置守卫
function(router, to, from, route, next) {
callHook(router.lifeCycle.routerBeforeHooks[0], to, from, router, next);
},
// 2. 组件beforeRouteLeave
function(router, to, from, route, next) {
callBeforeRouteLeave(router, to, from, next);
},
// 3. 路由beforeHooks
function(router, to, from, route, next) {
callHook(router.lifeCycle.beforeHooks[0], to, from, router, next);
},
// 4. 路由独享守卫beforeEnter
function(router, to, from, route, next) {
callHook(route.beforeEnter, to, from, router, next);
},
// 5. 路由afterHooks
function(router, to, from, route, next) {
router.$lockStatus = false;
if (router.options.platform === "h5") {
proxyH5Mount(router);
}
callHook(router.lifeCycle.afterHooks[0], to, from, router, next, false);
},
// 6. 全局后置守卫
function(router, to, from, route, next) {
router.$lockStatus = false;
if (router.options.platform === "h5") {
proxyH5Mount(router);
}
callHook(router.lifeCycle.routerAfterHooks[0], to, from, router, next, false);
}
];
// 循环调用钩子
function loopCallHook(hooks, index, next, router, to, from, NAVTYPE) {
// 如果所有钩子都执行完了
if (hooks.length - 1 < index) {
return next();
}
var hook = hooks[index];
var errorHook = ERRORHOOK[0];
// 调用钩子
hook(router, to, from, route, function(nextRule) {
// App平台tab切换特殊处理
if (router.options.platform === "app-plus") {
if (nextRule !== false &&
typeof nextRule !== "string" &&
typeof nextRule !== "object") {
tabIndexSelect(to, from);
}
}
// 1. next(false) - 终止导航
if (nextRule === false) {
if (router.options.platform === "h5") {
next(false);
}
errorHook({
type: 0,
msg: "管道函数传递 false 导航被终止!",
matTo: to,
matFrom: from,
nextTo: nextRule
}, router);
}
// 2. next(string|object) - 重定向
else if (typeof nextRule === "string" || typeof nextRule === "object") {
var redirectNAVTYPE = NAVTYPE;
var redirectRule = nextRule;
if (typeof nextRule === "object") {
var NAVTYPE_OVERRIDE = nextRule.NAVTYPE;
redirectRule = objectWithoutProperties(nextRule, ["NAVTYPE"]);
if (NAVTYPE_OVERRIDE != null) {
redirectNAVTYPE = NAVTYPE_OVERRIDE;
}
}
navjump(redirectRule, router, redirectNAVTYPE, { from, next });
}
// 3. next() - 继续
else if (nextRule == null) {
index++;
loopCallHook(hooks, index, next, router, to, from, NAVTYPE);
}
// 4. 其他 - 错误
else {
errorHook({
type: 1,
msg: "管道函数传递未知类型,无法被识别。导航被终止!",
matTo: to,
matFrom: from,
nextTo: nextRule
}, router);
}
});
}
// 转换导航
function transitionTo(router, to, from, NAVTYPE, hooks, finalCallback) {
var formattedRoutes = forMatNextToFrom(router, to, from);
var matTo = formattedRoutes.matTo;
var matFrom = formattedRoutes.matFrom;
// H5平台
if (router.options.platform === "h5") {
loopCallHook(hooks, 0, finalCallback, router, matTo, matFrom, NAVTYPE);
}
// 小程序/App平台
else {
// 分两步执行钩子
// 第一步前4个钩子
loopCallHook(hooks.slice(0, 4), 0, function() {
// 第二步后2个钩子在导航完成后
finalCallback(function() {
loopCallHook(hooks.slice(4), 0, voidFun, router, matTo, matFrom, NAVTYPE);
});
}, router, matTo, matFrom, NAVTYPE);
}
}
```
##### 页面钩子代理 (模块 845)
```javascript
// 代理页面生命周期钩子
function proxyPageHook(vueInstance, router, mpType) {
var proxyHookDeps = router.proxyHookDeps;
var options = vueInstance.$options;
var proxyHookNames = [
"onLoad", "onShow", "onReady", "onHide",
"onUnload", "onPullDownRefresh", "onReachBottom"
];
for (var i = 0; i < proxyHookNames.length; i++) {
var hookName = proxyHookNames[i];
var hooks = options[hookName];
if (hooks) {
for (var j = 0; j < hooks.length; j++) {
// 跳过已代理的钩子
if (hooks[j].toString().includes("UNI-SIMPLE-ROUTER")) {
continue;
}
var hookId = Object.keys(proxyHookDeps.hooks).length + 1;
// 创建代理函数
var proxyHook = function() {
var args = Array.prototype.slice.call(arguments);
proxyHookDeps.resetIndex.push(hookId);
proxyHookDeps.options[hookId] = args;
};
// 保存原始钩子
var originalHook = hooks.splice(j, 1, proxyHook)[0];
// 保存钩子信息
proxyHookDeps.hooks[hookId] = {
proxyHook: proxyHook,
callHook: function(path) {
// 只在匹配路径时调用
if (router.enterPath.replace(/^\//, "") === path.replace(/^\//, "") ||
mpType === "app") {
var args = proxyHookDeps.options[hookId];
originalHook.apply(vueInstance, args);
}
},
resetHook: function() {
hooks.splice(j, 1, originalHook);
}
};
}
}
}
}
// 重置并调用页面钩子
function resetAndCallPageHook(router, path, reset) {
if (reset === void 0) reset = true;
// 解析路径
var match = path.trim().match(/^(\/?[^\?\s]+)(\?[\s\S]*$)?$/);
if (match == null) {
throw new Error("还原hook失败。请检查 【" + path + "】 路径是否正确。");
}
path = match[1];
var proxyHookDeps = router.proxyHookDeps;
var resetIndex = proxyHookDeps.resetIndex;
// 调用所有钩子
for (var i = 0; i < resetIndex.length; i++) {
var hookId = resetIndex[i];
proxyHookDeps.hooks[hookId].callHook(path);
}
// 重置钩子
if (reset) {
resetPageHook(router);
}
}
```
---
### 2. 加密库
#### HMAC (模块 0116)
```javascript
/**
* HMAC - Hash-based Message Authentication Code
*
* 算法:
* HMAC(K, m) = H((K ⊕ opad) || H((K ⊕ ipad) || m))
*
* 其中:
* - K: 密钥
* - m: 消息
* - H: 哈希函数
* - ⊕: XOR运算
* - ||: 连接
* - ipad: 0x36重复blocksize次
* - opad: 0x5C重复blocksize次
*/
function Hmac(alg, key) {
// 1. 如果key是字符串转为Buffer
if (typeof key === "string") {
key = Buffer.from(key);
}
// 2. 确定blocksize
var blocksize = (alg === "sha512" || alg === "sha384") ? 128 : 64;
// 3. 处理key长度
if (key.length > blocksize) {
// key太长先hash
var hash = (alg === "rmd160") ? new rmd160() : sha(alg);
key = hash.update(key).digest();
} else if (key.length < blocksize) {
// key太短填充0
key = Buffer.concat([key, zeroBuffer], blocksize);
}
// 4. 计算ipad和opad
var ipad = Buffer.allocUnsafe(blocksize);
var opad = Buffer.allocUnsafe(blocksize);
for (var i = 0; i < blocksize; i++) {
ipad[i] = key[i] ^ 0x36;
opad[i] = key[i] ^ 0x5C;
}
// 5. 初始化内部hash
this._hash = (alg === "rmd160") ? new rmd160() : sha(alg);
this._hash.update(ipad);
}
Hmac.prototype._final = function() {
// 1. 计算内部hash
var innerHash = this._hash.digest();
// 2. 计算外部hash
var hash = (this._alg === "rmd160") ? new rmd160() : sha(this._alg);
return hash.update(this._opad).update(innerHash).digest();
};
```
支持的算法:
- MD5
- SHA1, SHA256, SHA384, SHA512
- RIPEMD160
#### Cipher (模块 0168)
加密/解密基类,提供:
- 缓冲区管理
- 分块处理
- 填充处理
#### Buffer (模块 5f79)
Node.js Buffer在浏览器环境的实现。
---
### 3. 核心Polyfills
#### Object方法
| 模块ID | 方法 | 说明 |
|--------|------|------|
| **00ca** | getOwnPropertyNames | 获取对象自身属性名 |
| **036b** | indexOf | 数组indexOf |
| **338c** | hasOwnProperty | 检查自身属性 |
| **f660** | toIndexedObject | 转为索引对象 |
#### Array方法
| 模块ID | 方法 | 说明 |
|--------|------|------|
| **bb80** | push | 数组push |
| **00c2** | keys | 对象键名 |
#### 工具函数
| 模块ID | 功能 | 说明 |
|--------|------|------|
| **2c2e** | inherits | 继承工具 |
| **cfef** | Transform | 流转换 |
| **d3c2** | assert | 断言 |
---
### 4. uni-simple-router 详细功能
#### 路由配置选项
```javascript
{
// 平台类型
platform: "h5" | "app-plus" | "mp-weixin" | "mp-alipay" | ...,
// 路由表
routes: [
{
path: "/pages/index/index",
name: "index",
aliasPath: "/",
meta: {},
beforeEnter: function(to, from, next) {}
}
],
// H5配置
h5: {
vueRouterDev: false,
vueNext: false,
paramsToQuery: false
},
// 小程序配置
applet: {
animationDuration: 300
},
// App配置
APP: {
animation: {
animationType: "pop-in",
animationDuration: 300
},
launchedHook: function() {}
},
// 调试
debugger: false | true | { err: true, warn: true, log: false },
// 守卫
routerBeforeEach: function(to, from, next) {},
routerAfterEach: function(to, from) {},
routerErrorEach: function(error, router) {},
// 查询处理
resolveQuery: function(query) { return query; },
parseQuery: function(query) { return query; },
// 检测锁
detectBeforeLock: function(router, to, navType) {}
}
```
#### 路由对象结构
```javascript
{
name: "index", // 路由名称
path: "/pages/index/index", // 路径
fullPath: "/pages/index/index?id=1", // 完整路径
query: { id: "1" }, // 查询参数
params: {}, // 路由参数
meta: {}, // 元信息
NAVTYPE: "push", // 导航类型
BACKTYPE: "" // 返回类型
}
```
#### API方法
```javascript
// 导航方法
router.push(location)
router.replace(location)
router.replaceAll(location)
router.pushTab(location)
router.back(delta, options)
// 守卫方法
router.beforeEach(fn)
router.afterEach(fn)
// 强制触发
router.forceGuardEach(NAVTYPE, passthrough)
// Vue实例访问
this.$Router // 路由器实例
this.$Route // 当前路由
this.$AppReady // App准备完成Promise
```
#### 原生方法重写
```javascript
// 重写uni原生导航方法
uni.navigateTo(options) router.push()
uni.redirectTo(options) router.replace()
uni.reLaunch(options) router.replaceAll()
uni.switchTab(options) router.pushTab()
uni.navigateBack(options) router.back()
```
---
## 模块依赖关系
```
607 (主入口)
├── 366 (常量)
├── 309 (类型)
├── 814 (加载页面)
└── 963 (创建路由)
├── 282 (配置)
├── 789 (工具)
├── 662 (钩子注册)
├── 460 (Mixins)
│ ├── 801 (路由映射)
│ ├── 844 (Vue路由)
│ ├── 147 (代理)
│ └── 814 (加载页面)
├── 890 (导航)
│ ├── 366 (常量)
│ ├── 99 (查询)
│ ├── 789 (工具)
│ ├── 169 (钩子调用)
│ └── 845 (页面钩子)
└── 314 (方法重写)
└── 809 (原生跳转)
```
---
## 性能优化
### 1. 代码分割
- 将第三方库独立打包
- 减少主bundle大小
- 利用浏览器缓存
### 2. 懒加载
- 页面组件按需加载
- 减少首屏加载时间
### 3. 压缩
- UglifyJS压缩
- 变量名混淆
- 移除注释和空格
---
## 建议
### 1. 优化建议
- ✅ 使用CDN加载常用库
- ✅ 启用Gzip/Brotli压缩
- ✅ 考虑按需引入uni-simple-router功能
- ✅ 分析是否所有加密库都需要
### 2. 调试建议
- 使用Source Map调试
- 启用路由debugger选项
- 查看原始源代码
### 3. 升级建议
- 检查依赖库版本
- 及时更新安全补丁
- 关注性能优化
---
## 总结
`chunk-vendors.4d47960d.js` 是一个包含所有第三方依赖的大型文件:
**主要内容**:
1. ✅ uni-simple-router (约70%代码量)
2. ✅ 加密库 (HMAC, SHA, MD5等)
3. ✅ Buffer实现
4. ✅ Polyfills (Object, Array方法)
5. ✅ 工具函数
**特点**:
- 📦 高度压缩1.18MB → 约26行
- 🔒 变量混淆
- ⚡ 模块化设计
- 🎯 独立打包
**用途**:
- 提供路由功能
- 提供加密功能
- 兼容性支持
- 工具函数库
由于文件过大且高度压缩,完整反编译需要原始源代码和构建配置。建议查看:
- uni-simple-router GitHub仓库
- 项目的package.json
- Webpack配置文件
---
## 附录模块ID速查表
### uni-simple-router核心模块
- 607: 主入口
- 366: 常量定义
- 963: 创建路由器
- 890: 导航跳转
- 169: 钩子调用
- 845: 页面钩子
- 789: 工具函数
- 99: 查询参数
- 314: 方法重写
- 662: 钩子注册
- 460: Mixins
- 282: 配置常量
### 加密相关
- 0116: HMAC
- 0168: Cipher
- 5f79: Buffer
- 1177: MD5
- 2d81: RMD160
- 25a4: SHA
### Polyfills
- 00c2: indexOf
- 00ca: getOwnPropertyNames
- bb80: array push
- 338c: hasOwnProperty
- f660: toIndexedObject
完整模块列表约200+个,这里仅列出主要模块。