#vitepress
VitePress 中使用 Axios 请求 HTTPS 接口时报 “certificate has expired” 错误的解决方案
在使用 VitePress 构建文档网站时,尝试通过 axios 请求一个 HTTPS 接口(例如在页面组件中获取远程数据),却在构建或运行时遇到如下错误:
cause: Error: certificate has expired
at TLSSocket.onConnectSecure (node:_tls_wrap:1679:34)
at TLSSocket.emit (node:events:507:28)
at TLSSocket._finishInit (node:_tls_wrap:1078:8)
at ssl.onhandshakedone (node:_tls_wrap:864:12) {
code: 'CERT_HAS_EXPIRED'
这是 Node.js 环境下 axios 请求一个 HTTPS 接口时,对方的证书过期 导致的,常见于:
- 使用旧的第三方服务接口
- 请求公司内网接口(自签名证书)
- 构建或预渲染阶段触发 HTTP 请求(如 VitePress 的 SSR)
✅ 问题定位关键点
- VitePress 是运行在 Node.js 环境中,使用 SSR(服务端渲染)预构建文档页面。
- 所以当你在 .md 或 theme 中的代码中写了类似:
import axios from 'axios'
axios.get('https://xxx.com/api/data')
会在 构建阶段执行,若目标接口证书过期,Node.js 默认会拒绝连接。
✅ 解决方案(按优先推荐顺序)
✅ 方案一: 避免 SSR 时发起请求
VitePress 会在构建时运行 SSR,如果你只想在浏览器中运行 axios 请求,必须用 onMounted 或 client-only 包裹。
VitePress 会在构建时运行 SSR,如果你只想在浏览器中运行 axios 请求,必须用 onMounted 或 client-only 包裹。
✅ 方法 1:用onMounted (推荐
<script setup>
import { onMounted, ref } from 'vue'
import axios from 'axios'
const data = ref(null)
onMounted(async () => {
try {
const res = await axios.get('https://xxx.com/api/data')
data.value = res.data
} catch (err) {
console.error(err)
}
})
</script>
✅ 这会让请求只在客户端浏览器中执行,避免 Node 处理 HTTPS 证书。
✅ 方案二:用 <ClientOnly>
包裹组件
<ClientOnly>
<YourComponent />
</ClientOnly>
适用于你把 axios 请求写在 Vue 组件里时。
✅ 方案三:开发/构建阶段临时忽略证书(仅用于调试)
如果你确实需要在构建阶段请求 HTTPS 接口,但对方证书已过期或是自签名,你可以在顶层设置:
// vitepress/config.js 或你自定义的 node 脚本中
process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0'
或者 axios 局部配置:
import https from 'https'
const agent = new https.Agent({ rejectUnauthorized: false })
axios.get('https://xxx.com/api/data', { httpsAgent: agent })
⚠️ 强烈不建议生产环境使用此方式。
✅ 总结
| 场景 | 解决方式 |
|---|---|
| 构建时 axios 请求失败 | 避免 SSR 请求,放在 onMounted 中执行 |
| 证书过期但必须构建时访问 | 使用 rejectUnauthorized: false 临时绕过 |
| 请求第三方/公司接口有证书问题 | 搭建代理中转层解决 |