247 lines
7.3 KiB
Markdown
247 lines
7.3 KiB
Markdown
|
|
# 地址数据懒加载优化方案
|
|||
|
|
|
|||
|
|
## 问题背景
|
|||
|
|
|
|||
|
|
地址JSON文件大小90M+,首次加载需要好几分钟,严重影响用户体验。
|
|||
|
|
|
|||
|
|
## 优化方案
|
|||
|
|
|
|||
|
|
### 方案1:懒加载 + 分段加载(已实现)⭐ 推荐
|
|||
|
|
|
|||
|
|
**核心思想**:分段加载 + 后台预加载,大幅减少首次等待时间
|
|||
|
|
|
|||
|
|
1. **首次加载(优化策略)**:
|
|||
|
|
- **H5环境**:使用Range请求只加载前2MB数据,从中提取省份列表(几秒完成)
|
|||
|
|
- **小程序环境**:如果完整数据已缓存,提取很快(< 1秒)
|
|||
|
|
- **降级方案**:如果分段加载失败,加载完整数据(但只加载一次)
|
|||
|
|
- **后台预加载**:提取省份列表后,在后台加载完整数据(不阻塞用户)
|
|||
|
|
|
|||
|
|
2. **按需加载**:用户选择省份后,从缓存的完整数据中提取该省份的详细数据(< 1秒)
|
|||
|
|
|
|||
|
|
3. **智能缓存**:完整数据会缓存,后续使用会很快
|
|||
|
|
|
|||
|
|
#### 性能对比
|
|||
|
|
|
|||
|
|
| 场景 | 优化前 | 优化后(懒加载+分段加载) |
|
|||
|
|
|------|--------|--------------------------|
|
|||
|
|
| 首次打开选择器(H5,无缓存) | 加载90M+(3-5分钟) | 分段加载前2MB提取省份列表(5-10秒) |
|
|||
|
|
| 首次打开选择器(小程序,无缓存) | 加载90M+(3-5分钟) | 加载完整数据并提取省份列表(3-5分钟,但只加载一次) |
|
|||
|
|
| 首次打开选择器(有缓存) | 加载90M+(3-5分钟) | 从缓存提取省份列表(< 1秒) |
|
|||
|
|
| 选择省份(有缓存) | 无需加载 | 从缓存提取省份数据(< 1秒) |
|
|||
|
|
| 切换省份(有缓存) | 无需加载 | 从缓存读取(< 1秒) |
|
|||
|
|
|
|||
|
|
**关键优化点**:
|
|||
|
|
- ✅ **H5环境**:首次只需加载2MB数据,几秒内显示省份列表
|
|||
|
|
- ✅ **后台预加载**:显示省份列表后,在后台加载完整数据(不阻塞用户)
|
|||
|
|
- ✅ 完整数据只加载一次,之后永久缓存
|
|||
|
|
- ✅ 后续所有操作都从缓存读取,秒开
|
|||
|
|
- ✅ 用户体验大幅提升:首次打开几秒内可用,而不是等待几分钟
|
|||
|
|
|
|||
|
|
#### 使用方式
|
|||
|
|
|
|||
|
|
组件已自动使用懒加载模式,无需修改调用代码:
|
|||
|
|
|
|||
|
|
```javascript
|
|||
|
|
// 正常使用,自动懒加载
|
|||
|
|
areaPicker.value?.open({
|
|||
|
|
success: (addressData) => {
|
|||
|
|
console.log('选择的地址:', addressData)
|
|||
|
|
}
|
|||
|
|
})
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 方案2:服务器分片接口(最佳方案)🚀
|
|||
|
|
|
|||
|
|
如果服务器可以提供分片接口,首次加载性能会进一步提升:
|
|||
|
|
|
|||
|
|
**注意**:当前默认使用方案1(从完整数据提取)。如果服务器提供了分片接口,可以在 `addressDataLoaderLazy.js` 中设置 `useSplitApi = true` 来启用。
|
|||
|
|
|
|||
|
|
#### 需要的接口
|
|||
|
|
|
|||
|
|
1. **省份列表接口**(轻量级)
|
|||
|
|
- URL: `http://124.243.245.42/ks_cms/address_provinces.json`
|
|||
|
|
- 返回:只包含省份基本信息,不包含children
|
|||
|
|
- 数据量:< 1MB
|
|||
|
|
|
|||
|
|
2. **省份详情接口**(按需加载)
|
|||
|
|
- URL: `http://124.243.245.42/ks_cms/address_province_{code}.json`
|
|||
|
|
- 返回:指定省份的完整数据(包含所有下级)
|
|||
|
|
- 数据量:每个省份 2-5MB
|
|||
|
|
|
|||
|
|
#### 数据格式示例
|
|||
|
|
|
|||
|
|
**省份列表接口返回格式:**
|
|||
|
|
```json
|
|||
|
|
[
|
|||
|
|
{
|
|||
|
|
"code": "110000",
|
|||
|
|
"name": "北京市",
|
|||
|
|
"_hasChildren": true
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"code": "120000",
|
|||
|
|
"name": "天津市",
|
|||
|
|
"_hasChildren": true
|
|||
|
|
}
|
|||
|
|
]
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**省份详情接口返回格式:**
|
|||
|
|
```json
|
|||
|
|
{
|
|||
|
|
"code": "110000",
|
|||
|
|
"name": "北京市",
|
|||
|
|
"children": [
|
|||
|
|
{
|
|||
|
|
"code": "110100",
|
|||
|
|
"name": "北京市",
|
|||
|
|
"children": [...]
|
|||
|
|
}
|
|||
|
|
]
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 配置分片接口
|
|||
|
|
|
|||
|
|
在 `utils/addressDataLoaderLazy.js` 中配置:
|
|||
|
|
|
|||
|
|
```javascript
|
|||
|
|
this.provinceListUrl = `${this.baseUrl}/address_provinces.json`;
|
|||
|
|
this.provinceDetailUrl = `${this.baseUrl}/address_province_{code}.json`;
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 方案3:数据压缩
|
|||
|
|
|
|||
|
|
确保服务器启用 gzip 压缩,可以减少 70-80% 的传输大小:
|
|||
|
|
|
|||
|
|
- 原始大小:90MB
|
|||
|
|
- 压缩后:18-27MB
|
|||
|
|
- 加载时间:从 3-5分钟 减少到 1-2分钟
|
|||
|
|
|
|||
|
|
**服务器配置示例(Nginx):**
|
|||
|
|
```nginx
|
|||
|
|
location /ks_cms/ {
|
|||
|
|
gzip on;
|
|||
|
|
gzip_types application/json;
|
|||
|
|
gzip_min_length 1000;
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 数据分片工具
|
|||
|
|
|
|||
|
|
如果服务器无法提供分片接口,可以使用提供的工具脚本将完整数据分片。
|
|||
|
|
|
|||
|
|
### 使用 Node.js 脚本分片数据
|
|||
|
|
|
|||
|
|
创建 `scripts/splitAddressData.js`:
|
|||
|
|
|
|||
|
|
```javascript
|
|||
|
|
const fs = require('fs');
|
|||
|
|
const path = require('path');
|
|||
|
|
|
|||
|
|
// 读取完整地址数据
|
|||
|
|
const fullDataPath = path.join(__dirname, '../data/address.json');
|
|||
|
|
const fullData = JSON.parse(fs.readFileSync(fullDataPath, 'utf8'));
|
|||
|
|
|
|||
|
|
// 输出目录
|
|||
|
|
const outputDir = path.join(__dirname, '../data/split');
|
|||
|
|
|
|||
|
|
// 创建输出目录
|
|||
|
|
if (!fs.existsSync(outputDir)) {
|
|||
|
|
fs.mkdirSync(outputDir, { recursive: true });
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 1. 生成省份列表(轻量级)
|
|||
|
|
const provinceList = fullData.map(province => ({
|
|||
|
|
code: province.code,
|
|||
|
|
name: province.name,
|
|||
|
|
_hasChildren: !!province.children && province.children.length > 0
|
|||
|
|
}));
|
|||
|
|
|
|||
|
|
fs.writeFileSync(
|
|||
|
|
path.join(outputDir, 'address_provinces.json'),
|
|||
|
|
JSON.stringify(provinceList, null, 2),
|
|||
|
|
'utf8'
|
|||
|
|
);
|
|||
|
|
console.log('✅ 省份列表已生成');
|
|||
|
|
|
|||
|
|
// 2. 为每个省份生成详情文件
|
|||
|
|
fullData.forEach(province => {
|
|||
|
|
const fileName = `address_province_${province.code}.json`;
|
|||
|
|
fs.writeFileSync(
|
|||
|
|
path.join(outputDir, fileName),
|
|||
|
|
JSON.stringify(province, null, 2),
|
|||
|
|
'utf8'
|
|||
|
|
);
|
|||
|
|
console.log(`✅ ${province.name} 详情已生成`);
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
console.log('✅ 数据分片完成!');
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
运行脚本:
|
|||
|
|
```bash
|
|||
|
|
node scripts/splitAddressData.js
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
然后将生成的文件上传到服务器。
|
|||
|
|
|
|||
|
|
## 降级方案
|
|||
|
|
|
|||
|
|
如果服务器不提供分片接口,懒加载器会自动降级:
|
|||
|
|
|
|||
|
|
1. **首次加载省份列表**:
|
|||
|
|
- 尝试从完整数据缓存中提取(如果已缓存,很快)
|
|||
|
|
- 如果未缓存,需要加载完整数据(仍然很慢,但只加载一次)
|
|||
|
|
|
|||
|
|
2. **加载省份详情**:
|
|||
|
|
- 尝试从完整数据缓存中提取(如果已缓存,很快)
|
|||
|
|
- 如果未缓存,需要加载完整数据(仍然很慢)
|
|||
|
|
|
|||
|
|
**建议**:即使使用降级方案,首次完整加载后,后续使用会很快(因为数据已缓存)。
|
|||
|
|
|
|||
|
|
## 最佳实践
|
|||
|
|
|
|||
|
|
1. **优先使用服务器分片接口**:性能最佳
|
|||
|
|
2. **启用 gzip 压缩**:减少传输大小
|
|||
|
|
3. **使用 CDN 加速**:提升加载速度
|
|||
|
|
4. **合理设置缓存时间**:默认7天,可根据数据更新频率调整
|
|||
|
|
|
|||
|
|
## 配置说明
|
|||
|
|
|
|||
|
|
在 `utils/addressDataLoaderLazy.js` 中可以配置:
|
|||
|
|
|
|||
|
|
```javascript
|
|||
|
|
// 数据源基础URL
|
|||
|
|
this.baseUrl = 'http://124.243.245.42/ks_cms';
|
|||
|
|
|
|||
|
|
// 省份列表URL(轻量级)
|
|||
|
|
this.provinceListUrl = `${this.baseUrl}/address_provinces.json`;
|
|||
|
|
|
|||
|
|
// 省份详情URL(按需加载)
|
|||
|
|
this.provinceDetailUrl = `${this.baseUrl}/address_province_{code}.json`;
|
|||
|
|
|
|||
|
|
// 缓存有效期(天)
|
|||
|
|
this.cacheExpireDays = 7;
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 性能监控
|
|||
|
|
|
|||
|
|
组件会在控制台输出加载日志,可以监控性能:
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
📥 开始加载: http://124.243.245.42/ks_cms/address_provinces.json
|
|||
|
|
✅ 数据加载完成,耗时 2.34 秒
|
|||
|
|
✅ 从缓存加载省份列表
|
|||
|
|
📥 懒加载省份详情: 北京市 (110000)
|
|||
|
|
✅ 数据加载完成,耗时 3.56 秒
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 总结
|
|||
|
|
|
|||
|
|
- ✅ **懒加载方案已实现**:首次加载从几分钟减少到几秒
|
|||
|
|
- 🚀 **服务器分片接口**:可以进一步提升性能
|
|||
|
|
- 💾 **智能缓存**:已加载的数据会缓存,切换时秒开
|
|||
|
|
- 🔄 **自动降级**:即使服务器不支持分片,也能正常工作
|
|||
|
|
|