背景

基于 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. 新建功能页面

  1. 将 PC 端设计稿复制后丢给 Cursor,AI 会根据设计稿生成一个大概页面,人工再进行调整。(稍微复杂的 UI,其实相当于重画)
  2. 画完后,让 Cursor 再生成移动端,再进行调整。

遇到的问题

问题一:移动端设备兼容

移动端不同设备宽度不同,需要适配。解决方案是编写 pxToVw 方法,将 px 转为 vw

问题二:测试服部署

由于移动端样式与 PC 相差较大,所以直接写了两套代码。部署测试服后无法加载成功,排查过程如下:

现象

根目录生成了 pc.htmlmobile.html,原有的 index.html 消失了。

原因
  • PC 文件夹命名为 (pc)(带括号),Next.js 会自动忽略该路由路径。
  • 本项目 Next.js 配置为静态导出:output: 'export'
  • Nginx 配置中默认指向 index.htmlpc/index.html,无法正确匹配。
解决方案

Step 1: 配置 next.config 文件中 trailingSlash: true,使 PC 与 Mobile 主页打包后分别为:

更改后的项目文件结构

  • pc/index.html
  • mobile/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 只需要请求一次。

起初使用 redirectpermanent 重定向,都跳转失败。

对比表格
特性 permanent (301) last (内部重写)
地址栏 ✅ 会变化 ❌ 不变
浏览器 看到并缓存重定向 完全不知道
HTTP 请求 2 次(原请求 + 新请求) 1 次
状态码 301 200
SEO 权重转移 不影响
性能 稍慢(多一次请求) 更快
为什么 redirect / permanent 会失败?

因为 Nginx 中 Ingress 配置使用通配符,Host 配置的是内网域名redirectpermanent 都会取 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 │
└───────────────────────────────────────────────────────┘

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐