jinbi-utils 1.0.19 → 1.0.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.babelrc +19 -0
- package/.cz-config.js +55 -0
- package/.dockerignore +3 -0
- package/.editorconfig +12 -0
- package/.eslintignore +8 -0
- package/.eslintrc.js +54 -0
- package/.versionrc.json +9 -0
- package/CHUNK_OPTIMIZER_USAGE.md +132 -0
- package/Dockerfile +3 -0
- package/QUICK_RELEASE.md +85 -0
- package/RELEASE_GUIDE.md +243 -0
- package/api-extractor.json +15 -0
- package/commitlint.config.js +3 -0
- package/jest.config.js +15 -0
- package/package.json +8 -35
- package/rollup.config.chunk-optimizer.js +32 -0
- package/rollup.config.js +73 -0
- package/src/array/index.ts +85 -0
- package/src/build/chunk-optimizer/ARCHITECTURE.md +347 -0
- package/src/build/chunk-optimizer/QUICK_START.md +370 -0
- package/src/build/chunk-optimizer/README.md +240 -0
- package/src/build/chunk-optimizer/core/chunk-generator.ts +166 -0
- package/src/build/chunk-optimizer/core/classifier.ts +148 -0
- package/src/build/chunk-optimizer/core/dependency-reader.ts +138 -0
- package/src/build/chunk-optimizer/examples/basic-usage.ts +234 -0
- package/src/build/chunk-optimizer/index.ts +166 -0
- package/src/build/chunk-optimizer/rules/common-rules.ts +131 -0
- package/src/build/chunk-optimizer/rules/framework-rules.ts +93 -0
- package/src/build/chunk-optimizer/rules/index.ts +27 -0
- package/src/build/chunk-optimizer/test.ts +94 -0
- package/src/build/chunk-optimizer/types.ts +128 -0
- package/src/color/index.ts +58 -0
- package/src/common/index.ts +353 -0
- package/src/constant/common.constant.ts +13 -0
- package/src/date/index.ts +143 -0
- package/src/dom/index.ts +198 -0
- package/src/file/index.ts +319 -0
- package/src/http/apiBuilder/README.md +648 -0
- package/src/http/apiBuilder/api-builder.ts +502 -0
- package/src/http/apiBuilder/example.ts +243 -0
- package/src/http/apiBuilder/index.ts +1 -0
- package/src/http/apiBuilder//345/277/253/351/200/237/345/217/202/350/200/203.md +199 -0
- package/src/http/http.ts +79 -0
- package/src/http/httpEnums.ts +61 -0
- package/src/iam/index.ts +46 -0
- package/src/index.ts +20 -0
- package/src/middleware/requestLogger.middware.ts +371 -0
- package/src/middleware/requestLoggerUnified.ts +371 -0
- package/src/number/index.ts +362 -0
- package/src/object/index.ts +54 -0
- package/src/print/index.ts +102 -0
- package/src/string/index.ts +189 -0
- package/src/utils/curl.ts +108 -0
- package/src/validate/index.ts +100 -0
- package/src/websocket/emitter.ts +39 -0
- package/src/websocket/index.ts +6 -0
- package/src/websocket/manager.ts +151 -0
- package/src/websocket/pinia-store.ts +91 -0
- package/src/websocket/service.ts +34 -0
- package/src/websocket/types.ts +45 -0
- package/test/common/index.test.ts +19 -0
- package/test/date/index.test.ts +107 -0
- package/test/file/index.test.ts +104 -0
- package/test/number/index.test.ts +108 -0
- package/test/object/index.test.ts +20 -0
- package/test/string/index.test.ts +82 -0
- package/tsconfig.json +39 -0
- package/typedoc.json +12 -0
- package/types/file/index.d.ts +7 -0
- package/types/index.d.ts +1 -0
- package/types/websocket/emitter.d.ts +16 -0
- package/types/websocket/index.d.ts +6 -0
- package/types/websocket/manager.d.ts +36 -0
- package/types/websocket/pinia-store.d.ts +25 -0
- package/types/websocket/service.d.ts +13 -0
- package/types/websocket/types.d.ts +34 -0
- package/dist/chunk-optimizer.cjs +0 -703
- package/dist/index.esm.js +0 -2791
- package/dist/index.esm.min.js +0 -15
- package/dist/index.umd.js +0 -2899
- package/dist/index.umd.min.js +0 -16
package/package.json
CHANGED
|
@@ -1,46 +1,19 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "jinbi-utils",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.21",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "dist/index.umd.min.js",
|
|
6
6
|
"module": "dist/index.esm.min.js",
|
|
7
7
|
"typings": "types/index.d.ts",
|
|
8
|
-
"files": [
|
|
9
|
-
"dist",
|
|
10
|
-
"types",
|
|
11
|
-
"README.md",
|
|
12
|
-
"CHANGELOG.md"
|
|
13
|
-
],
|
|
14
|
-
"exports": {
|
|
15
|
-
".": {
|
|
16
|
-
"types": "./types/index.d.ts",
|
|
17
|
-
"import": "./dist/index.esm.min.js",
|
|
18
|
-
"require": "./dist/index.umd.min.js",
|
|
19
|
-
"default": "./dist/index.esm.min.js"
|
|
20
|
-
},
|
|
21
|
-
"./chunk-optimizer": {
|
|
22
|
-
"types": "./types/build/chunk-optimizer/index.d.ts",
|
|
23
|
-
"require": "./dist/chunk-optimizer.min.cjs",
|
|
24
|
-
"default": "./dist/chunk-optimizer.min.cjs"
|
|
25
|
-
}
|
|
26
|
-
},
|
|
27
8
|
"scripts": {
|
|
28
9
|
"dev": "cross-env NODE_ENV=development rollup -w -c",
|
|
29
|
-
"build": "
|
|
30
|
-
"build:main": "cross-env NODE_ENV=production rollup -c",
|
|
31
|
-
"build:chunk-optimizer": "rollup -c rollup.config.chunk-optimizer.js",
|
|
10
|
+
"build": "cross-env NODE_ENV=production rollup -c && npm run build:docs",
|
|
32
11
|
"watch:dist": "nodemon --watch ./dist --exec 'yalc publish --force'",
|
|
33
12
|
"build:docs": "typedoc",
|
|
34
13
|
"lint:fix": "eslint src/** --fix",
|
|
35
14
|
"lint": "eslint src/**",
|
|
36
15
|
"test": "jest --coverage",
|
|
37
|
-
"test:dev": "jest --watch --coverage"
|
|
38
|
-
"prepublishOnly": "npm run build",
|
|
39
|
-
"release:major": "npm run build && standard-version --release-as major && npm publish && git push --follow-tags",
|
|
40
|
-
"release:minor": "npm run build && standard-version --release-as minor && npm publish && git push --follow-tags",
|
|
41
|
-
"release:patch": "npm run build && standard-version --release-as patch && npm publish && git push --follow-tags",
|
|
42
|
-
"release:beta": "npm run build && standard-version --prerelease beta && npm publish --tag beta && git push --follow-tags",
|
|
43
|
-
"release": "npm run release:patch"
|
|
16
|
+
"test:dev": "jest --watch --coverage"
|
|
44
17
|
},
|
|
45
18
|
"keywords": [
|
|
46
19
|
"fe-utils",
|
|
@@ -63,7 +36,6 @@
|
|
|
63
36
|
"@commitlint/cli": "^11.0.0",
|
|
64
37
|
"@commitlint/config-conventional": "^11.0.0",
|
|
65
38
|
"@types/jest": "^25.2.3",
|
|
66
|
-
"@types/node": "^24.10.0",
|
|
67
39
|
"@typescript-eslint/eslint-plugin": "^3.0.2",
|
|
68
40
|
"@typescript-eslint/parser": "^3.0.2",
|
|
69
41
|
"axios": "1.8.2",
|
|
@@ -85,9 +57,7 @@
|
|
|
85
57
|
"rollup-plugin-serve": "^1.0.1",
|
|
86
58
|
"rollup-plugin-terser": "^6.1.0",
|
|
87
59
|
"rollup-plugin-typescript2": "^0.27.1",
|
|
88
|
-
"standard-version": "^9.5.0",
|
|
89
60
|
"ts-jest": "^26.0.0",
|
|
90
|
-
"tslib": "^2.8.1",
|
|
91
61
|
"typedoc": "^0.17.8",
|
|
92
62
|
"typedoc-plugin-external-module-name": "^4.0.3",
|
|
93
63
|
"typescript": "^3.9.3"
|
|
@@ -103,7 +73,10 @@
|
|
|
103
73
|
"commit-msg": "exit 0"
|
|
104
74
|
}
|
|
105
75
|
},
|
|
106
|
-
"
|
|
107
|
-
"
|
|
76
|
+
"dependencies": {
|
|
77
|
+
"@wecom/jssdk": "^2.3.1",
|
|
78
|
+
"pinia": "^2.1.7",
|
|
79
|
+
"tslib": "^2.8.1",
|
|
80
|
+
"vue": "^3.4.0"
|
|
108
81
|
}
|
|
109
82
|
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import babel from 'rollup-plugin-babel';
|
|
2
|
+
import typescript from 'rollup-plugin-typescript2';
|
|
3
|
+
import { terser } from 'rollup-plugin-terser';
|
|
4
|
+
|
|
5
|
+
const output = [
|
|
6
|
+
{
|
|
7
|
+
file: 'dist/chunk-optimizer.cjs',
|
|
8
|
+
format: 'cjs',
|
|
9
|
+
},
|
|
10
|
+
];
|
|
11
|
+
|
|
12
|
+
if (process.env.NODE_ENV === 'production') {
|
|
13
|
+
output.push({
|
|
14
|
+
file: 'dist/chunk-optimizer.min.cjs',
|
|
15
|
+
format: 'cjs',
|
|
16
|
+
plugins: [terser()],
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export default {
|
|
21
|
+
input: 'src/build/chunk-optimizer/index.ts',
|
|
22
|
+
output,
|
|
23
|
+
external: ['fs', 'path'],
|
|
24
|
+
plugins: [
|
|
25
|
+
typescript({
|
|
26
|
+
useTsconfigDeclarationDir: true,
|
|
27
|
+
}),
|
|
28
|
+
babel({
|
|
29
|
+
exclude: 'node_modules/**',
|
|
30
|
+
}),
|
|
31
|
+
],
|
|
32
|
+
};
|
package/rollup.config.js
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import babel from 'rollup-plugin-babel';
|
|
2
|
+
import { eslint } from "rollup-plugin-eslint";
|
|
3
|
+
import typescript from 'rollup-plugin-typescript2';
|
|
4
|
+
import cleaner from 'rollup-plugin-cleaner';
|
|
5
|
+
import { terser } from "rollup-plugin-terser";
|
|
6
|
+
import serve from 'rollup-plugin-serve';
|
|
7
|
+
import pkg from './package.json';
|
|
8
|
+
|
|
9
|
+
// 端口
|
|
10
|
+
const PORT = 3001;
|
|
11
|
+
// 是否是生产
|
|
12
|
+
const IS_PROD = process.env.NODE_ENV === 'production';
|
|
13
|
+
|
|
14
|
+
const formats = ['umd', 'esm'];
|
|
15
|
+
const output = formats.map((format) => ({
|
|
16
|
+
file: `dist/index.${format}.js`,
|
|
17
|
+
format,
|
|
18
|
+
name: pkg.name,
|
|
19
|
+
globals: {
|
|
20
|
+
'axios': 'axios',
|
|
21
|
+
'pinia': 'pinia'
|
|
22
|
+
}
|
|
23
|
+
}));
|
|
24
|
+
|
|
25
|
+
// 生成模式生成压缩文件
|
|
26
|
+
if (IS_PROD) {
|
|
27
|
+
formats.forEach((format) => {
|
|
28
|
+
output.push({
|
|
29
|
+
file: `dist/index.${format}.min.js`,
|
|
30
|
+
format,
|
|
31
|
+
name: pkg.name,
|
|
32
|
+
globals: {
|
|
33
|
+
'axios': 'axios',
|
|
34
|
+
'pinia': 'pinia'
|
|
35
|
+
},
|
|
36
|
+
plugins: [terser()],
|
|
37
|
+
});
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export default {
|
|
42
|
+
input: 'src/index.ts',
|
|
43
|
+
output,
|
|
44
|
+
external: ['fsevents', 'axios', 'pinia', 'fs', 'path'],
|
|
45
|
+
plugins: [
|
|
46
|
+
eslint({
|
|
47
|
+
fix: true,
|
|
48
|
+
exclude: 'node_modules/**'
|
|
49
|
+
}),
|
|
50
|
+
// 使用 tsconfig.json 中定义 的 declarationDir
|
|
51
|
+
typescript({
|
|
52
|
+
useTsconfigDeclarationDir: true,
|
|
53
|
+
}),
|
|
54
|
+
babel({
|
|
55
|
+
exclude: 'node_modules/**',
|
|
56
|
+
}),
|
|
57
|
+
cleaner({
|
|
58
|
+
targets: [
|
|
59
|
+
'./dist/',
|
|
60
|
+
'./types/'
|
|
61
|
+
]
|
|
62
|
+
}),
|
|
63
|
+
!IS_PROD && (
|
|
64
|
+
serve({
|
|
65
|
+
open: false,
|
|
66
|
+
contentBase: ['dist', 'example'],
|
|
67
|
+
historyApiFallback: true,
|
|
68
|
+
host: 'localhost',
|
|
69
|
+
port: PORT,
|
|
70
|
+
})
|
|
71
|
+
),
|
|
72
|
+
],
|
|
73
|
+
};
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 数组处理相关
|
|
3
|
+
* @packageDocumentation
|
|
4
|
+
* @module Array
|
|
5
|
+
* @preferred
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* 从对象数组中提取指定 key 的值,组成新数组
|
|
10
|
+
* @param arr - 对象数组
|
|
11
|
+
* @param key - 要提取的键名
|
|
12
|
+
* @returns 提取的值数组
|
|
13
|
+
*/
|
|
14
|
+
export function getKeyList<T extends Record<string, any>>(
|
|
15
|
+
arr: T[],
|
|
16
|
+
key: string
|
|
17
|
+
): any[] {
|
|
18
|
+
if (!Array.isArray(arr)) return [];
|
|
19
|
+
|
|
20
|
+
const result: any[] = [];
|
|
21
|
+
for (const item of arr) {
|
|
22
|
+
if (item && item[key] !== undefined && item[key] !== null) {
|
|
23
|
+
result.push(item[key]);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return result;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* 判断父数组是否包含子数组的所有元素(深度比较)
|
|
32
|
+
* 注意:此函数需要配合深度比较工具使用
|
|
33
|
+
* @param parent - 父数组
|
|
34
|
+
* @param children - 子数组
|
|
35
|
+
* @param compareFn - 比较函数,用于判断两个元素是否相等
|
|
36
|
+
* @returns 是否包含所有子元素
|
|
37
|
+
*/
|
|
38
|
+
export function isIncludeAllChildren<T>(
|
|
39
|
+
parent: T[],
|
|
40
|
+
children: T[],
|
|
41
|
+
compareFn?: (a: T, b: T) => boolean
|
|
42
|
+
): boolean {
|
|
43
|
+
if (!Array.isArray(parent) || !Array.isArray(children)) return false;
|
|
44
|
+
|
|
45
|
+
const defaultCompareFn = (a: T, b: T) => JSON.stringify(a) === JSON.stringify(b);
|
|
46
|
+
const compare = compareFn || defaultCompareFn;
|
|
47
|
+
|
|
48
|
+
return children.every(child => parent.some(item => compare(item, child)));
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* 判断数组或对象是否为空
|
|
53
|
+
* @param value - 待检查的值
|
|
54
|
+
* @returns 是否为空
|
|
55
|
+
*/
|
|
56
|
+
export function isAllEmpty(value: any): boolean {
|
|
57
|
+
if (value === null || value === undefined) return true;
|
|
58
|
+
if (typeof value === 'string') return value.trim().length === 0;
|
|
59
|
+
if (Array.isArray(value)) return value.length === 0;
|
|
60
|
+
if (typeof value === 'object') return Object.keys(value).length === 0;
|
|
61
|
+
return false;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* 计算两个数组的交集
|
|
66
|
+
* @param arr1 - 数组1
|
|
67
|
+
* @param arr2 - 数组2
|
|
68
|
+
* @returns 交集数组
|
|
69
|
+
*/
|
|
70
|
+
export function intersection<T>(arr1: T[], arr2: T[]): T[] {
|
|
71
|
+
if (!Array.isArray(arr1) || !Array.isArray(arr2)) return [];
|
|
72
|
+
return arr1.filter(item => arr2.includes(item));
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* 数组求和
|
|
77
|
+
* @param arr - 数字数组
|
|
78
|
+
* @returns 数组元素之和
|
|
79
|
+
*/
|
|
80
|
+
export function sum(arr: number[]): number {
|
|
81
|
+
return Array.isArray(arr) && arr.length > 0
|
|
82
|
+
? arr.reduce((acc, val) => acc + val, 0)
|
|
83
|
+
: 0;
|
|
84
|
+
}
|
|
85
|
+
|
|
@@ -0,0 +1,347 @@
|
|
|
1
|
+
# Chunk Optimizer 架构设计文档
|
|
2
|
+
|
|
3
|
+
## 📐 整体架构
|
|
4
|
+
|
|
5
|
+
```
|
|
6
|
+
┌─────────────────────────────────────────────────────────────┐
|
|
7
|
+
│ Vite Config │
|
|
8
|
+
│ import { createChunkOptimizer } from './build/...' │
|
|
9
|
+
│ const optimizer = createChunkOptimizer(options) │
|
|
10
|
+
│ manualChunks: optimizer.generate() │
|
|
11
|
+
└────────────────────┬────────────────────────────────────────┘
|
|
12
|
+
│
|
|
13
|
+
▼
|
|
14
|
+
┌─────────────────────────────────────────────────────────────┐
|
|
15
|
+
│ ChunkOptimizer (主类) │
|
|
16
|
+
│ ┌──────────────────────────────────────────────────────┐ │
|
|
17
|
+
│ │ 职责: │ │
|
|
18
|
+
│ │ - 协调各个模块 │ │
|
|
19
|
+
│ │ - 管理配置选项 │ │
|
|
20
|
+
│ │ - 提供公共 API │ │
|
|
21
|
+
│ └──────────────────────────────────────────────────────┘ │
|
|
22
|
+
└────────────────────┬────────────────────────────────────────┘
|
|
23
|
+
│
|
|
24
|
+
┌────────────┼────────────┐
|
|
25
|
+
▼ ▼ ▼
|
|
26
|
+
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
|
|
27
|
+
│ Dependency │ │ Dependency │ │ Chunk │
|
|
28
|
+
│ Reader │→│ Classifier │→│ Generator │
|
|
29
|
+
└──────────────┘ └──────────────┘ └──────────────┘
|
|
30
|
+
│ │ │
|
|
31
|
+
▼ ▼ ▼
|
|
32
|
+
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
|
|
33
|
+
│ package.json │ │ Rules DB │ │ manualChunks │
|
|
34
|
+
└──────────────┘ └──────────────┘ └──────────────┘
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## 🧩 核心模块
|
|
38
|
+
|
|
39
|
+
### 1. DependencyReader(依赖读取器)
|
|
40
|
+
|
|
41
|
+
**职责:**
|
|
42
|
+
- 读取和解析 `package.json`
|
|
43
|
+
- 提取依赖信息
|
|
44
|
+
- 自动检测项目框架
|
|
45
|
+
|
|
46
|
+
**核心方法:**
|
|
47
|
+
```typescript
|
|
48
|
+
class DependencyReader {
|
|
49
|
+
getDependencies(): DependencyInfo[]
|
|
50
|
+
detectFramework(): Framework
|
|
51
|
+
hasDependency(name: string): boolean
|
|
52
|
+
getDependencyVersion(name: string): string | null
|
|
53
|
+
}
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
**设计要点:**
|
|
57
|
+
- 缓存 `package.json` 内容,避免重复读取
|
|
58
|
+
- 区分生产依赖和开发依赖
|
|
59
|
+
- 提供框架自动检测功能
|
|
60
|
+
|
|
61
|
+
---
|
|
62
|
+
|
|
63
|
+
### 2. DependencyClassifier(依赖分类器)
|
|
64
|
+
|
|
65
|
+
**职责:**
|
|
66
|
+
- 根据规则对依赖进行分类
|
|
67
|
+
- 支持自定义规则
|
|
68
|
+
- 处理排除规则
|
|
69
|
+
|
|
70
|
+
**核心方法:**
|
|
71
|
+
```typescript
|
|
72
|
+
class DependencyClassifier {
|
|
73
|
+
classifyDependency(dep: DependencyInfo): DependencyCategory | null
|
|
74
|
+
classifyAll(dependencies: DependencyInfo[]): DependencyInfo[]
|
|
75
|
+
getCategoryStats(dependencies: DependencyInfo[]): Record<string, number>
|
|
76
|
+
printClassification(dependencies: DependencyInfo[]): void
|
|
77
|
+
}
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
**分类优先级:**
|
|
81
|
+
1. 自定义规则(最高优先级)
|
|
82
|
+
2. 排除规则
|
|
83
|
+
3. 预定义规则(按 priority 排序)
|
|
84
|
+
4. 默认分类(vendor-libs)
|
|
85
|
+
|
|
86
|
+
**规则匹配逻辑:**
|
|
87
|
+
```typescript
|
|
88
|
+
// 1. 精确匹配
|
|
89
|
+
if (packageName === rule.match) return rule.category;
|
|
90
|
+
|
|
91
|
+
// 2. 正则匹配
|
|
92
|
+
if (rule.match.test(packageName)) return rule.category;
|
|
93
|
+
|
|
94
|
+
// 3. 通配符匹配(自定义规则)
|
|
95
|
+
if (pattern.includes('*')) {
|
|
96
|
+
const regex = new RegExp('^' + pattern.replace(/\*/g, '.*') + '$');
|
|
97
|
+
if (regex.test(packageName)) return category;
|
|
98
|
+
}
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
---
|
|
102
|
+
|
|
103
|
+
### 3. ChunkGenerator(Chunk 生成器)
|
|
104
|
+
|
|
105
|
+
**职责:**
|
|
106
|
+
- 生成 `manualChunks` 函数
|
|
107
|
+
- 处理 node_modules 依赖
|
|
108
|
+
- 处理业务代码分包
|
|
109
|
+
|
|
110
|
+
**核心方法:**
|
|
111
|
+
```typescript
|
|
112
|
+
class ChunkGenerator {
|
|
113
|
+
generate(): ManualChunksFunction
|
|
114
|
+
getStats(): { totalDependencies, categorizedDependencies, categories }
|
|
115
|
+
printStats(): void
|
|
116
|
+
}
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
**分包逻辑:**
|
|
120
|
+
```typescript
|
|
121
|
+
manualChunks(id: string) {
|
|
122
|
+
// 1. 处理 node_modules 依赖
|
|
123
|
+
if (id.includes('node_modules')) {
|
|
124
|
+
const packageName = extractPackageName(id);
|
|
125
|
+
return dependencyMap.get(packageName);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// 2. 处理业务代码
|
|
129
|
+
if (id.includes('/src/views/')) {
|
|
130
|
+
return extractModuleName(id); // chunk-{module}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
if (id.includes('/src/components/')) {
|
|
134
|
+
return 'chunk-components';
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// ... 其他业务代码规则
|
|
138
|
+
}
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
---
|
|
142
|
+
|
|
143
|
+
### 4. Rules(规则库)
|
|
144
|
+
|
|
145
|
+
**结构:**
|
|
146
|
+
```
|
|
147
|
+
rules/
|
|
148
|
+
├── index.ts # 规则导出和聚合
|
|
149
|
+
├── framework-rules.ts # 框架相关规则
|
|
150
|
+
└── common-rules.ts # 通用库规则
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
**规则定义:**
|
|
154
|
+
```typescript
|
|
155
|
+
interface Rule {
|
|
156
|
+
match: string | RegExp; // 匹配模式
|
|
157
|
+
category: DependencyCategory; // 分类
|
|
158
|
+
priority?: number; // 优先级(越大越高)
|
|
159
|
+
description?: string; // 描述
|
|
160
|
+
}
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
**规则分类:**
|
|
164
|
+
- **框架规则**:Vue、React、Angular、Svelte
|
|
165
|
+
- **通用规则**:工具库、图标库、UI 库、图表库等
|
|
166
|
+
|
|
167
|
+
---
|
|
168
|
+
|
|
169
|
+
## 🔄 工作流程
|
|
170
|
+
|
|
171
|
+
### 1. 初始化阶段
|
|
172
|
+
|
|
173
|
+
```typescript
|
|
174
|
+
const optimizer = createChunkOptimizer(options);
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
1. 合并默认配置和用户配置
|
|
178
|
+
2. 创建 `DependencyReader` 实例
|
|
179
|
+
3. 自动检测框架(如果 `framework: 'auto'`)
|
|
180
|
+
4. 创建 `DependencyClassifier` 实例
|
|
181
|
+
|
|
182
|
+
### 2. 分析阶段
|
|
183
|
+
|
|
184
|
+
```typescript
|
|
185
|
+
const result = optimizer.analyze();
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
1. 读取 `package.json` 中的所有依赖
|
|
189
|
+
2. 对每个依赖进行分类
|
|
190
|
+
3. 生成分类统计信息
|
|
191
|
+
4. 返回分析结果
|
|
192
|
+
|
|
193
|
+
### 3. 生成阶段
|
|
194
|
+
|
|
195
|
+
```typescript
|
|
196
|
+
const manualChunks = optimizer.generate();
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
1. 执行分析(如果还未分析)
|
|
200
|
+
2. 创建 `ChunkGenerator` 实例
|
|
201
|
+
3. 构建依赖名称到分类的映射
|
|
202
|
+
4. 生成并返回 `manualChunks` 函数
|
|
203
|
+
|
|
204
|
+
### 4. 构建阶段
|
|
205
|
+
|
|
206
|
+
```typescript
|
|
207
|
+
// Vite 构建时调用
|
|
208
|
+
manualChunks(id, { getModuleInfo })
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
1. Vite 对每个模块调用 `manualChunks` 函数
|
|
212
|
+
2. 根据模块 ID 判断是 node_modules 还是业务代码
|
|
213
|
+
3. 返回对应的 chunk 名称
|
|
214
|
+
4. Vite 根据返回值进行分包
|
|
215
|
+
|
|
216
|
+
---
|
|
217
|
+
|
|
218
|
+
## 🎯 设计原则
|
|
219
|
+
|
|
220
|
+
### 1. 单一职责原则(SRP)
|
|
221
|
+
|
|
222
|
+
每个类只负责一个功能:
|
|
223
|
+
- `DependencyReader` 只负责读取依赖
|
|
224
|
+
- `DependencyClassifier` 只负责分类
|
|
225
|
+
- `ChunkGenerator` 只负责生成配置
|
|
226
|
+
|
|
227
|
+
### 2. 开闭原则(OCP)
|
|
228
|
+
|
|
229
|
+
- 对扩展开放:可以添加新的规则、新的框架支持
|
|
230
|
+
- 对修改封闭:核心逻辑不需要修改
|
|
231
|
+
|
|
232
|
+
### 3. 依赖倒置原则(DIP)
|
|
233
|
+
|
|
234
|
+
- 依赖抽象(接口/类型)而非具体实现
|
|
235
|
+
- 使用 TypeScript 类型系统保证类型安全
|
|
236
|
+
|
|
237
|
+
### 4. 可测试性
|
|
238
|
+
|
|
239
|
+
- 每个模块都可以独立测试
|
|
240
|
+
- 提供测试脚本和示例
|
|
241
|
+
|
|
242
|
+
---
|
|
243
|
+
|
|
244
|
+
## 🔌 扩展点
|
|
245
|
+
|
|
246
|
+
### 1. 添加新的框架支持
|
|
247
|
+
|
|
248
|
+
在 `rules/framework-rules.ts` 中添加:
|
|
249
|
+
|
|
250
|
+
```typescript
|
|
251
|
+
export const newFrameworkRules: Rule[] = [
|
|
252
|
+
{ match: 'new-framework', category: 'vendor-framework', priority: 100 },
|
|
253
|
+
// ...
|
|
254
|
+
];
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
### 2. 添加新的通用规则
|
|
258
|
+
|
|
259
|
+
在 `rules/common-rules.ts` 中添加:
|
|
260
|
+
|
|
261
|
+
```typescript
|
|
262
|
+
export const newCategoryRules: Rule[] = [
|
|
263
|
+
{ match: 'new-lib', category: 'vendor-new', priority: 60 },
|
|
264
|
+
// ...
|
|
265
|
+
];
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
### 3. 自定义分包策略
|
|
269
|
+
|
|
270
|
+
未来可以实现不同的策略类:
|
|
271
|
+
|
|
272
|
+
```typescript
|
|
273
|
+
interface Strategy {
|
|
274
|
+
name: string;
|
|
275
|
+
apply(dependencies: DependencyInfo[]): DependencyInfo[];
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
class BalancedStrategy implements Strategy { ... }
|
|
279
|
+
class AggressiveStrategy implements Strategy { ... }
|
|
280
|
+
class ConservativeStrategy implements Strategy { ... }
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
---
|
|
284
|
+
|
|
285
|
+
## 📊 性能考虑
|
|
286
|
+
|
|
287
|
+
### 1. 缓存机制
|
|
288
|
+
|
|
289
|
+
- `package.json` 读取结果缓存
|
|
290
|
+
- 依赖分类结果缓存
|
|
291
|
+
- 避免重复计算
|
|
292
|
+
|
|
293
|
+
### 2. 规则匹配优化
|
|
294
|
+
|
|
295
|
+
- 规则按优先级排序,高优先级规则先匹配
|
|
296
|
+
- 使用 Map 存储依赖分类映射,O(1) 查找
|
|
297
|
+
- 正则表达式预编译
|
|
298
|
+
|
|
299
|
+
### 3. 构建时性能
|
|
300
|
+
|
|
301
|
+
- `manualChunks` 函数会被频繁调用
|
|
302
|
+
- 使用简单的字符串匹配和 Map 查找
|
|
303
|
+
- 避免复杂的计算和 I/O 操作
|
|
304
|
+
|
|
305
|
+
---
|
|
306
|
+
|
|
307
|
+
## 🚀 未来优化方向
|
|
308
|
+
|
|
309
|
+
### 1. 包大小分析
|
|
310
|
+
|
|
311
|
+
- 读取 `node_modules` 中的包大小
|
|
312
|
+
- 根据大小动态调整分包策略
|
|
313
|
+
- 大包单独分离,小包合并
|
|
314
|
+
|
|
315
|
+
### 2. 依赖关系分析
|
|
316
|
+
|
|
317
|
+
- 分析包之间的依赖关系
|
|
318
|
+
- 将强相关的包打包在一起
|
|
319
|
+
- 减少重复代码
|
|
320
|
+
|
|
321
|
+
### 3. 智能策略
|
|
322
|
+
|
|
323
|
+
- 基于项目类型自动选择策略
|
|
324
|
+
- 基于历史构建数据优化分包
|
|
325
|
+
- 机器学习预测最优分包方案
|
|
326
|
+
|
|
327
|
+
### 4. 可视化工具
|
|
328
|
+
|
|
329
|
+
- 提供 Web UI 查看分包结果
|
|
330
|
+
- 可视化依赖关系图
|
|
331
|
+
- 交互式调整分包规则
|
|
332
|
+
|
|
333
|
+
---
|
|
334
|
+
|
|
335
|
+
## 📝 总结
|
|
336
|
+
|
|
337
|
+
这个架构设计具有以下优点:
|
|
338
|
+
|
|
339
|
+
✅ **模块化** - 清晰的职责划分,易于维护
|
|
340
|
+
✅ **可扩展** - 易于添加新规则和新功能
|
|
341
|
+
✅ **类型安全** - 完整的 TypeScript 类型定义
|
|
342
|
+
✅ **高性能** - 优化的匹配算法和缓存机制
|
|
343
|
+
✅ **易用性** - 简单的 API,零配置即可使用
|
|
344
|
+
✅ **可测试** - 每个模块都可以独立测试
|
|
345
|
+
|
|
346
|
+
这是一个生产级别的工具,可以直接用于实际项目中。
|
|
347
|
+
|