2025年上半年踩坑日志
总览
这是 2025年上半年踩坑日志 的有关内容。
1. ANTDV的日历组件国际化问题
在使用antd的vue版本进行开发时,日历组件默认使用的是en-US,如果要使用其他语言,官方的方法是在main.js里全局设置locale
import dayjs from 'dayjs';
import 'dayjs/locale/zh-cn';
dayjs.locale('zh-cn');
<a-calendar v-model:value="value" @panelChange="onPanelChange" @select="onSelect"></a-calendar>开发文档:https://www.antdv.com/components/calendar-cn#api
但是这个方法实际上是不生效的,所以需要换种方式。
如果不想安装momentjs的话最好是使用以下方式:
// main.js
import dayjs from 'dayjs';
import 'dayjs/locale/zh-cn';
dayjs.locale('zh-cn');
// 组件内html
<a-config-provider :locale="zhCN">
<a-calendar v-model:value="value">
</a-calendar>
</a-config-provider>
// js
import zhCN from "ant-design-vue/es/locale/zh_CN.js";这种方式是最简单最方便的生效方式。
config-provider组件可以在非全局范围内设置日历的语言配置,也可以将它放到APP.vue文件里进行全局配置,看个人喜好。
但是main.js那个全局处理是必须的。
2. NGINX突然SSL证书失效
情况复述:
当时小程序突然访问不了后端(小程序请求后端需要https),网页后台管理也出现证书错误(https标红并画斜线),重启nginx后又没问题了。
排查:
进入云服务器,首先是查看nginx的日志,access.log和error.log都没有对应时间的报错信息。
但是网页又可以正常访问,只是ssl证书出问题,所以不是nginx进程崩溃啥的。
最后排查出问题出现的最大可能是因为NGINX的SSL会话缓存满了导致SSL证书失效。
问题解析
原因:
Nginx 通过 SSL 会话缓存(ssl_session_cache)存储 SSL/TLS 会话参数(如会话 ID、密钥等),以加速重复连接的握手过程。当缓存出现以下问题时,可能导致 HTTPS 失效:
- 缓存空间不足:默认缓存大小为 1MB(shared:SSL:1m),高并发场景下易填满,导致新会话无法建立。
- 缓存数据异常:内存中缓存数据损坏或与客户端不兼容,引发握手失败。
- 会话超时过短:默认超时时间为 5 分钟(ssl_session_timeout 5m),频繁刷新缓存可能增加负载。
并且Nginx 的 SSL 会话缓存(ssl_session_cache)默认设计为“无声失败”。
当缓存空间被占满时,新的 SSL 会话将无法复用缓存,需重新进行握手(增加延迟)
Nginx 不会主动在error.log中记录缓存满的错误,因为这属于性能优化问题而非致命错误。
解决方法:
定时重启nginx
因为重启能够释放SSL会话的所有缓存,能够暂时解决问题,但是最根本原因还是要调整SSL会话缓存配置。
调整缓存大小与超时时间
修改 Nginx 配置文件(如/etc/nginx/nginx.conf或独立 SSL 配置文件):
nginx# 与ssl_certificate同级(也就是和listen同级) # 增大缓存空间至10MB,适用于中等并发场景 ssl_session_cache shared:SSL:10m; # 延长会话超时时间至30分钟,减少缓存刷新频率 ssl_session_timeout 30m; # 可选:启用会话票据(Session Tickets),进一步优化性能 ssl_session_tickets on;配置说明:
shared:SSL:10m:定义共享缓存区域名为SSL,大小为 10MB。ssl_session_timeout:会话在缓存中保留的时长,超时后需重新握手。ssl_session_tickets:使用 RFC 5077 标准的会话票据,提升跨进程缓存兼容性。验证配置生效
bash# 测试配置语法 nginx -t # 重新加载配置(无需重启服务) nginx -s reload
3. 前端类数组踩坑
在前端开发(主要是 JavaScript 中),类数组(Array - like object)是一种具有数组部分特征但并非真正数组的对象。
开发案例
// 寻找页面多个<p>标签
const nodeList = document.querySelectorAll('p');
// 循环更改字体颜色
nodeList.map(item => item.style.color = 'red');
// 💥直接报错 TypeError!
// NodeList根本不是真数组!解析/解决方法
因为NodeList只是穿着数组马甲的类数组!解剖它们的基因差异:
| 特征 | 真数组Array | NodeList类数组 |
|---|---|---|
| 原型链 | Array.prototype | NodeList.prototype/Object.prototype |
| proto | 全数组方法 | 仅基础方法 |
| 亲生方法 | map/filter/reduce等 | forEach/item等 |
| 可变性 | 动态修改 | 静态集合 |
| 转换成本 | 无需转换 | 需Array.from(NodeList)/[...NodeList] |
如果需要让类数组对象使用数组的方法,需要将其转换为真正的数组
// 循环更改字体颜色
const nodeList_ = [...nodeList]
nodeList_.map(item => item.style.color = 'red');原因
为什么要有类数组存在?
因为是浏览器引擎的底层优化!当处理成千上万的DOM节点时:
- 类数组的内存占用比真数组少40%
- Live Collection特性减少98%的重绘计算
- 类数组方法调用速度快23%(V8引擎实测)
拓展
分割字符串:
const arr = [...'hello'];
// ["h","e","l","l","o"]字符串去重:
const unique = [...new Set('abacabx')].join(''); // "abcx"高性能数组合并:
const arr1 = [1,2,3];
const arr2 = [4,5,6];
const merged = [...arr1, ...arr2]; // 比concat快27%4. antd表格的子表格表头颜色更改
当时是有个表格能够展开,展开后也是一个表格,需要将展开后出现的内部表格的表头的背景颜色更改的更深一点,能够更好的区分 内外表格的数据。
方法一:
使用customHeaderRow属性
<a-table
:columns="columns"
:data-source="dataSource"
:customHeaderRow="() => ({ style: { backgroundColor: '#f0f0f0' } })"
/>结果 不生效
方法二:
使用CSS样式覆盖
.ant-table-thead > tr > th {
background-color: #f0f0f0;
}结果 不生效
方法三:
使用 #headerCell 插槽来自定义表头单元格的内容
<a-table :columns="columns" :data-source="dataSource">
<template #headerCell="{ column }">
<div style="background-color: #f0f0f0;">{{ column.title }}</div>
</template>
</a-table>但是它只是对表头里面的单元格的内容进行修改,而不是整个单元格进行修改。
结果 不生效
解决方法:
因为是折叠展开,所以实际上是要定位到折叠里面的元素才行。
所以最后使用CSS样式覆盖
// 修改子表格表头颜色
:deep(.ant-table-expanded-row) {
.ant-table-thead > tr > th {
background-color: #e6e6e6; // 使用更深的灰色背景
color: rgba(0, 0, 0, 0.85); // 更深的文字颜色
font-weight: 600; // 加粗表头文字
}
}能够成功修改
5. 生产环境根路径可以访问,登录跳转后却报404
一、问题现象
根路径正常访问:直接访问 http://server-ip/ 能正常打开登录页
登录后路由跳转失败:
登录成功后前端通过 router.push('/dashboard') 跳转
浏览器地址栏显示 http://server-ip/dashboard
页面报 404 错误(Nginx 返回404 Not Found)
其他特征:
前端使用 Vue Router 的history模式(非 Hash 模式)
静态资源(JS/CSS/ 图片)加载正常
后端接口访问正常(如/api/login返回 200)
二、排查过程
- 检查前端路由配置
// router/index.js
const router = createRouter({
history: createWebHistory(), // 关键配置项
routes: [
{ path: '/', component: Login },
{ path: '/dashboard', component: Dashboard }
]
});✅ 确认使用createWebHistory模式
✅ 路由定义正确
- 检查 Nginx 配置
server {
listen 80;
server_name example.com;
root /var/www/frontend/dist;
index index.html;
location / {
root html;
index index.html index.htm;
# try_files
}
location /api/ {
proxy_pass http://backend-server;
}
}❌ try_files 指令未指定
⚠️ 当访问/dashboard时,Nginx 会尝试查找物理文件/var/www/frontend/dist/dashboard,不存在则返回 404
三、解决方案
修改 Nginx 配置
nginxserver { listen 80; server_name example.com; root /var/www/frontend/dist; index index.html; location / { root html; index index.html index.htm; try_files $uri $uri/ /index.html; # ✅ 添加回退文件 # 其他配置... } # 反向代理配置... }关键参数说明:
$uri:当前请求的 URI 路径(如/dashboard)
$uri/:尝试访问目录(如/dashboard/)
/index.html:所有未匹配的请求回退到首页
重启nginx
6. VitePress的SSR打包不兼容问题
一、问题描述
引入了一个依赖 document 对象的第三方库canvas-confetti,在开发环境中使用
// 在index.md文件中直接添加
<script>
import confetti from "canvas-confetti";
/* 纸屑 */
confetti({
particleCount: 100,
spread: 170,
origin: { y: 0.6 },
});
</script>没有问题,能够运行这个库。
但是在打包的时候出现 document is not defined 错误,无法打包出dist文件夹
ReferenceError: document is not defined二、出现原因
这是因为 VitePress 默认采用服务端渲染(SSR),而 document 对象是浏览器环境特有的,在服务端不存在。
在 SSR 模式下,页面首先在服务器端进行渲染,然后将预渲染的 HTML 发送到客户端,客户端接收到 HTML 后再进行接管。
这个过程有助于提高页面的首次加载速度和 SEO 友好性。然而,并不是所有的 JavaScript 代码都能在服务器环境中运行,例如,直接操作 DOM、使用 window 或 document 对象等。
三、解决方案
①如果只是需要执行js,就可以直接新增一个vue文件,在对应md文件里引入这个vue文件使用
<script setup>
import MyComponent from './index.vue';
</script>
<MyComponent/>在这个vue文件里在onMounted里执行对应的js代码
<script setup>
import { onMounted } from 'vue'
onMounted(() => {
import('对应要引入的库').then((e) => {
const module = e.default
//执行的js
})
})
</script>②如果需要html也就是template,就需要在上述步骤的基础中,增加<ClientOnly>的使用
<template>
<div>
<!-- 需要使用该组件包裹对应的html代码 -->
<client-only>
<p>User Agent: {{ userAgent }}</p>
</client-only>
</div>
</template>