首页 > 其他分享 >next.js 利用中间件(middleware.ts)实现PC与移动互相丝滑跳转

next.js 利用中间件(middleware.ts)实现PC与移动互相丝滑跳转

时间:2024-07-04 17:55:33浏览次数:19  
标签:丝滑 mobile 中间件 PATH PC indexOf 跳转 const landingpage

场景描述

产品要求开发一个落地页,为了美观,他要求这个两个页面分开设计,PC页面路由是`/landingpage`,移动端页面是`/landingpage/mobile`

从用户角度出发,现在有一种访问场景,假如用户A正在访问PC页面`/landingpage`,然后他要把这个页面以微信方式分享给用户B,用户通过手机方式打开,那这个时候用户用手机看到的就是PC端页面

要解决上面的场景问题,有以下几种方案

1. 在页面上利用`getServerSideProps` 进行定向,弊端:假如我有很多这样的页面,那就要在每个页面写相同的重定向代码

2. 写通用逻辑hooks判断当前环境,根据环境跳转至不同的路由,弊端:hooks是客户端方法,要执行该方法首先的进入浏览器客户端,然后根据条件跳转不同的地址,这个时候就会出现闪烁

3. 利用中间件(middleware.ts)可实现丝滑无感跳转,原理就是重定向

hooks版本

useMobileAndPcBridging.ts

import { useRouter } from 'next/router'

const PC_MOBILE_LIST = [
  ['/landingpage/amazon', '/landingpage/amazon/mobile'],
  ['/landingpage/goOut', '/landingpage/goOut/mobile'],
  ['/landingpage/vppa', '/landingpage/vppa/mobile'],
  ['/gec/introduce', '/gec/introduce/mobile'],
  ['/greenCertificate/introduce', '/greenCertificate/introduce/mobile'],
  ['/landingpage/intention', '/landingpage/intention/mobile'],
  ['/landingpage/coscoShipping', '/landingpage/coscoShipping/mobile']
]
const useMobileAndPcBridging = () => {
  const router = useRouter()
  if (!process.browser) return
  const { pathname, query } = router
  const ITEM = PC_MOBILE_LIST.find((value) => value.includes(pathname))
  if (!ITEM?.length) return
  const [PC_PATH, MOBILE_PATH] = ITEM
  if (window.device.mobile && MOBILE_PATH !== pathname) {
    router.push({
      pathname: MOBILE_PATH,
      query
    })
    return
  }

  if (!window.device.mobile && PC_PATH !== pathname) {
    router.push({
      pathname: PC_PATH,
      query
    })
    return
  }
}

export default useMobileAndPcBridging

 

中间件middleware.ts版本

middleware.ts

import { NextResponse } from 'next/server'
import { type NextRequest } from 'next/server'
import { equipment } from '@/utils'

const PC_MOBILE_LIST = [
  ['/landingpage/amazon', '/landingpage/amazon/mobile'],
  ['/landingpage/goOut', '/landingpage/goOut/mobile'],
  ['/landingpage/vppa', '/landingpage/vppa/mobile'],
  ['/gec/introduce', '/gec/introduce/mobile'],
  ['/greenCertificate/introduce', '/greenCertificate/introduce/mobile'],
  ['/landingpage/intention', '/landingpage/intention/mobile'],
  ['/landingpage/coscoShipping', '/landingpage/coscoShipping/mobile']
]

export function middleware(request: NextRequest) {
  const userAgent = request.headers.get('user-agent') || ''
  const { pathname, search } = request.nextUrl
  const device = equipment(userAgent)
  const ITEM = PC_MOBILE_LIST.find((value) => value.includes(pathname))
  if (!ITEM?.length) return NextResponse.next()
  const [PC_PATH, MOBILE_PATH] = ITEM
  if (device.mobile && MOBILE_PATH !== pathname) {
    const path = new URL(MOBILE_PATH + search, request.url)
    console.log('移动端,跳转中...' + MOBILE_PATH)
    return NextResponse.redirect(path)
  }

  if (!device.mobile && PC_PATH !== pathname) {
    console.log('PC端,跳转中...' + PC_PATH)
    const path = new URL(PC_PATH + search, request.url)
    return NextResponse.redirect(path)
  }
  return NextResponse.next()
}

export const config = {
  matcher: [PC_MOBILE_LIST.flat(1)]
}

 

上面代码中遇到了辅助函数判断设备 `equipment`,这里贴以下方法

utils/index.ts

export const equipment = function (userAgent?: string) {
  //判断终端
  const u = userAgent || window.navigator.userAgent
  return {
    trident: u.indexOf('Trident') > -1, //IE内核
    presto: u.indexOf('Presto') > -1, //opera内核
    webKit: u.indexOf('AppleWebKit') > -1, //苹果、谷歌内核
    gecko: u.indexOf('Gecko') > -1 && u.indexOf('KHTML') == -1, //火狐内核
    mobile: !!u.match(/AppleWebKit.*Mobile.*/) || u.indexOf('Samsung') > -1, //是否为移动终端
    ios: !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/), //ios终端
    android: u.indexOf('Android') > -1 || u.indexOf('Linux') > -1, //android终端或者uc浏览器
    iPhone: u.indexOf('iPhone') > -1 || u.indexOf('Mac') > -1, //是否为iPhone或者安卓QQ浏览器
    iPad: u.indexOf('iPad') > -1, //是否为iPad
    webApp: u.indexOf('Safari') == -1, //是否为web应用程序,没有头部与底部
    weixin: u.indexOf('MicroMessenger') > -1 //是否为微信浏览器
  }
}

 

标签:丝滑,mobile,中间件,PATH,PC,indexOf,跳转,const,landingpage
From: https://www.cnblogs.com/yz-blog/p/18284330

相关文章

  • 鸿蒙手机号&&验证码登录, 包含倒计时&&号码格式验证码格式校验, 还有 使用 Hyperlink
    1,先看看整体效果                          2,看格式校验效果                            3,代码直接CV  importpromptActionfrom'@ohos.promptA......
  • 丝滑解决ImportError: /usr/lib/x86_64-linux-gnu/libstdc++.so.6: version `GLIBCXX_
    基础环境:MacOSm1、python=3.9前情提要:在Anaconda终端运行代码的时候,显示报错:importError:/usr/lib/x86_64-linux-gnu/libstdc++.so.6:version`GLIBCXX_3.4.29'notfound1问题分析:根据提示是/usr/lib/x86_64-linux-gnu/路径下的libstdc++.so.6缺少版本GLIBCXX_3.4.29解......
  • camunda如何实现流程跳转和流程退回
    我们在使用工作流的时候,常常有“流程退回”、“流程跳转”、“自由流”、“动态加签”等这样的需求。Camunda流程平台提供了这样的机制和接口,虽然流程模型定义活动执行顺序的序列流,但有时需要灵活地重新启动活动或取消正在运行的活动,进而可以实现中国特色的流程需求。文本重点讲如......
  • Django框架之Cookie和Session概念,Django操作cookie,Django操作Session,CBV添加装饰器
    ⅠDjango框架之Cookie和Session概念【一】Cookie与Session的发展史Cookie和Session是用来在Web应用程序中跟踪用户会话数据的两种常用技术。【1】Cookie的发展史1994年,网景通信公司推出了第一个浏览器Cookie技术。Cookie是存储在用户计算机上的小型文本文件,用于跟踪用户......
  • Windows服务器下配置Gogs HTTP自动跳转HTTPS
    在前面的文章中,介绍了如何在Windows服务器下搭建自己的git服务器,在文末介绍了开启HTTPS的方法。https://www.cnblogs.com/zhaotianff/p/17887191.html 但是开启https后,无法使用http访问了,所以需要urlrewrite,找了一圈,发现网上的教程都是Linux下基于Nginx的。 通过尝试,找到......
  • 华为云技术专家硬核分享,云原生中间件如何加速业务发展
    本文分享自华为云社区《云原生中间件,构筑软件安全可信的连接桥梁》,作者:华为云PaaS服务小智。近日,在华为云开发者大会2024期间,来自华为云PaaS服务,中间件领域产品团队的资深专家、技术总监、高级产品经理等大咖们发表了以“云原生中间件,构筑软件安全可信的连接桥梁”为主题的专题......
  • 7、 Django-路由-router-页面跳转
    概念:在实际开发过程中、一个Django项目会包含很多的app、这时候如果我们只在主路由里进行配置就会显得杂乱无章、所以通常在每个app中创建各自的urls.py路由模块、然后从根路由出发、将app所属的url请求、全部转发到相应的urls.py模块而这个从主路由转发到各个应用的路由的过......
  • 初学者必读:如何使用 Nuxt 中间件简化网站开发
    title:初学者必读:如何使用Nuxt中间件简化网站开发date:2024/6/24updated:2024/6/24author:cmdragonexcerpt:本文概述了Nuxt3框架的升级特点,对比Nuxt2,详细解析中间件应用、配置策略与实战示例,涵盖功能、错误管理、优化技巧,并探讨与Nuxt3核心组件集成方法,给出最佳......
  • Linux各个中间件日志位置
    Linux各个中间件日志位置Linux系统中各种常见中间件日志文件的默认位置取决于安装时的配置以及中间件的具体类型。以下是一些常见中间件日志文件的标准位置ApacheHTTPServer:访问日志:/var/log/httpd/access_log或/var/log/apache2/access.log ......
  • java使用@Controller注解跳转到thmyleaf页面时候报错
     报错如下######当我使用RestController时候接口可以得到返回的对象↓但是查看RestController和Controller的区别之后:也就是说@RestController返回的是一个对象,@Controller默认情况下,方法的返回值会被解析为一个视图名称,并寻找与该名称匹配的视图进行渲染。这意味着返回......