官网适配移动端与 PC 端实战遇到的问题总结
摘要 本项目基于Next.js+Ant Design+UnoCSS实现PC端页面适配移动端及新增产品展示页面。通过Cursor的Figma MCP工具生成移动端代码,并为复杂UI创建两套代码方案。遇到的主要问题是移动端设备兼容和测试部署问题:通过编写pxToVw方法解决响应式布局问题;针对Nginx部署问题,配置trailingSlash:true使PC/Mobile分别生成index.html,
背景
基于 Next.js + Ant Design + UnoCSS 创建的纯前端项目,本期需要将已有的 PC 页面兼容移动端,并创建一个新的产品展示页面,一并兼容移动端。
具体实现
1. 已有 PC 页面实现移动端
利用 Cursor → Figma 的 MCP,配置本项目 Rule 如下:
你是一名高级前端工程师,需要基于 UI 设计稿实现前端网页交互。
本项目为 Next.js + @ant-design 搭建的纯前端官网项目,已实现 PC 端页面,现在需要根据 UI 设计稿,实现移动端页面。所有的数据资源,与 PC 端保持一致,页面跳转交互也一样,只是样式有些差异。完成页面代码时,以优先参考 UI,交互以及数据参考 PC 端对应页面实现。
用户会在每次会话中给到 Figma UI 设计稿 MCP 描述。
接着让 Cursor 后台跑,每个页面都新建一个会话,以防上下文过长。
2. 新建功能页面
- 将 PC 端设计稿复制后丢给 Cursor,AI 会根据设计稿生成一个大概页面,人工再进行调整。(稍微复杂的 UI,其实相当于重画)
- 画完后,让 Cursor 再生成移动端,再进行调整。
遇到的问题
问题一:移动端设备兼容
移动端不同设备宽度不同,需要适配。解决方案是编写 pxToVw 方法,将 px 转为 vw。
问题二:测试服部署
由于移动端样式与 PC 相差较大,所以直接写了两套代码。部署测试服后无法加载成功,排查过程如下:
现象
根目录生成了 pc.html 与 mobile.html,原有的 index.html 消失了。
原因
- PC 文件夹命名为
(pc)(带括号),Next.js 会自动忽略该路由路径。 - 本项目 Next.js 配置为静态导出:
output: 'export'。 - Nginx 配置中默认指向
index.html或pc/index.html,无法正确匹配。
解决方案
Step 1: 配置 next.config 文件中 trailingSlash: true,使 PC 与 Mobile 主页打包后分别为:

pc/index.htmlmobile/index.html
Step 2: 修改后仍然不成功,需要配置 Nginx 根据设备类型指向不同的入口文件:
map $http_user_agent $is_mobile {
default 0;
~*(Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera\ Mini) 1;
}
map $is_mobile $device_prefix {
0 /pc;
1 /mobile;
}
map $is_mobile $ua_index_fallback {
0 /pc/index.html;
1 /mobile/index.html;
}
map $uri $index_fallback {
default $ua_index_fallback;
~^/pc(/|$) /pc/index.html;
~^/mobile(/|$) /mobile/index.html;
}
server {
listen 80;
listen [::]:80;
server_name localhost;
server_name_in_redirect off;
root /usr/share/nginx/html;
index index.html;
# 已带前缀的路径,直接处理
location ~ ^/(pc|mobile) {
add_header Cache-Control no-cache;
add_header X-Device-Prefix $device_prefix always;
add_header X-Is-Mobile $is_mobile always;
add_header X-Uri $uri always;
add_header X-Request-Filename $request_filename always;
# Next.js trailingSlash:true 模式,优先尝试目录的 index.html
try_files $uri $uri/index.html $uri.html $index_fallback;
}
# 静态资源直接处理
location ~ \.(css|js|png|jpg|jpeg|gif|svg|webp|ico|woff2?|ttf|otf|map|json)$ {
try_files $uri =404;
}
# _next、api 等 Next.js 资源
location ~ ^/(?:_next|api) {
try_files $uri =404;
}
location / {
# 根路径重写到对应端首页
if ($uri = /) {
rewrite ^ $device_prefix/ last;
}
# 其他路径加前缀后重新匹配(保留尾斜杠)
rewrite ^(.*)$ $device_prefix$1 last;
}
# 增加缓存配置
location ~* .*\.(?:htm|html)$ {
add_header Cache-Control no-cache;
}
error_page 500 502 503 504 /50x.html;
}
关键点:rewrite ... last vs 重定向
其中核心配置:
location / {
if ($uri = /) {
rewrite ^ $device_prefix/ last;
}
rewrite ^(.*)$ $device_prefix$1 last;
}
使用 rewrite ... last 可实现 Nginx 内部重定向,即 HTTP 只需要请求一次。
起初使用 redirect 和 permanent 重定向,都跳转失败。
对比表格
| 特性 | permanent (301) |
last (内部重写) |
|---|---|---|
| 地址栏 | ✅ 会变化 | ❌ 不变 |
| 浏览器 | 看到并缓存重定向 | 完全不知道 |
| HTTP 请求 | 2 次(原请求 + 新请求) | 1 次 |
| 状态码 | 301 | 200 |
| SEO | 权重转移 | 不影响 |
| 性能 | 稍慢(多一次请求) | 更快 |
为什么 redirect / permanent 会失败?
因为 Nginx 中 Ingress 配置使用通配符,Host 配置的是内网域名,redirect 或 permanent 都会取 Ingress 中的 Host,导致域名错误。而 last 是 Nginx 内部重写,不会改变地址栏。
失败流程:
用户请求: Host: 外部域名.cn
↓
[Ingress] 改成内部域名
↓
转发给后端: Host: 内部域名.cn
↓
[Nginx 容器]
- 收到 Host: 内部域名.cn
- 生成 301: Location: http://内部域名/mobile/
↓ 返回给用户
用户浏览器: 跳转到 内部域名.cn ❌
附运维架构
┌───────────────────────────────────────────────────────┐
│ 公网 │
│ 用户浏览器 │
│ https://外部域名.cn │
└────────────────────┬──────────────────────────────────┘
↓ DNS 解析到公网 IP
┌───────────────────────────────────────────────────────┐
│ Kubernetes 集群边界 │
│ [Ingress Controller] │
│ - 公网 IP: 47.x.x.x │
│ - TLS 证书处理 │
│ - 应该设置: proxy_set_header Host $host; │
└────────────────────┬──────────────────────────────────┘
↓ 内部 HTTP 转发
┌───────────────────────────────────────────────────────┐
│ 内网 (Kubernetes 内部网络) │
│ [Service: nginx-service] │
│ - ClusterIP: 10.**.x.x │
│ - 内部 DNS: nginx-service.default.svc.cluster.local │
│ │
│ [Pod: Nginx 容器] │
│ - Pod IP: 172.x.x.x │
│ - hostname: 内部域名.cn │
└───────────────────────────────────────────────────────┘
更多推荐



所有评论(0)