You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Next.js PWA项目中如何为Manifest.json的short_name字段设置动态值

解决方案

_document.tsx仅在服务端首次渲染时执行,作为静态HTML生成的入口,无法直接处理用户态的动态数据(比如登录后的用户名),静态引用的manifest.json是固定资源自然无法修改。

下面提供两种可直接落地的实现方案:

方案1:使用Next.js API路由动态生成Manifest(推荐)

步骤1:创建API路由文件

根据你使用的Next.js路由模式选择对应代码:

Pages Router写法

在pages/api目录下新建manifest.ts文件:

// pages/api/manifest.ts
import type { NextApiRequest, NextApiResponse } from 'next'

export default async function handler(
  req: NextApiRequest,
  res: NextApiResponse
) {
  // 可从请求Cookie中拿登录态,也可在此处直接调用后端接口获取用户名
  const userName = req.cookies.userName || '默认应用名'
  // 按业务需求拼接short_name字段
  const shortName = `${userName}的工作台`

  const manifest = {
    name: '你的完整应用名称',
    short_name: shortName,
    // 其他manifest原有配置原样保留即可,比如icons、start_url、display等
    start_url: '/',
    display: 'standalone',
    background_color: '#ffffff',
    theme_color: '#000000',
    icons: [
      {
        src: '/icon-192x192.png',
        sizes: '192x192',
        type: 'image/png'
      }
    ]
  }

  res.setHeader('Content-Type', 'application/json')
  res.setHeader('Cache-Control', 'public, max-age=0, must-revalidate')
  res.status(200).json(manifest)
}

App Router写法

在app/api/manifest目录下新建route.ts文件:

// app/api/manifest/route.ts
import { cookies } from 'next/headers'
import { NextResponse } from 'next/server'

export async function GET() {
  const cookieStore = cookies()
  const userName = cookieStore.get('userName')?.value || '默认应用名'
  const shortName = `${userName}的工作台`

  const manifest = {
    name: '你的完整应用名称',
    short_name: shortName,
    start_url: '/',
    display: 'standalone',
    background_color: '#ffffff',
    theme_color: '#000000',
    icons: [
      {
        src: '/icon-192x192.png',
        sizes: '192x192',
        type: 'image/png'
      }
    ]
  }

  return NextResponse.json(manifest, {
    headers: {
      'Content-Type': 'application/json',
      'Cache-Control': 'public, max-age=0, must-revalidate'
    }
  })
}

步骤2:修改manifest引用路径

替换_document.tsx中原有的静态manifest引用:

// _document.tsx 的Head标签内
<Head>
  <link rel="manifest" href="/api/manifest" />
  {/* 其他原有meta标签保留 */}
</Head>

方案2:客户端动态注入Manifest(适合用户名仅存在前端的场景)

如果用户名仅存储在前端localStorage,不需要请求后端,可选择该方案:

步骤1:删除_document.tsx中原有的静态manifest引用

步骤2:在应用入口添加动态注入逻辑

在_app.tsx(Pages Router)或根layout.tsx(App Router)中添加代码:

import { useEffect } from 'react'
import type { AppProps } from 'next/app'

export default function App({ Component, pageProps }: AppProps) {
  useEffect(() => {
    // 从前端存储获取用户名
    const userName = localStorage.getItem('userName') || '默认应用名'
    const shortName = `${userName}的工作台`

    const manifest = {
      // 填入你的全量manifest配置
      name: '你的完整应用名称',
      short_name: shortName,
      start_url: '/',
      display: 'standalone',
      background_color: '#ffffff',
      theme_color: '#000000',
      icons: [
        {
          src: '/icon-192x192.png',
          sizes: '192x192',
          type: 'image/png'
        }
      ]
    }

    // 生成blob格式的manifest地址
    const blob = new Blob([JSON.stringify(manifest)], { type: 'application/json' })
    const manifestUrl = URL.createObjectURL(blob)

    // 移除旧manifest标签
    const oldManifest = document.querySelector('link[rel="manifest"]')
    if (oldManifest) oldManifest.remove()

    // 插入新manifest标签
    const link = document.createElement('link')
    link.rel = 'manifest'
    link.href = manifestUrl
    document.head.appendChild(link)

    // 清理内存
    return () => URL.revokeObjectURL(manifestUrl)
  }, [])

  return <Component {...pageProps} />
}

注意事项

  • 优先选择方案1,兼容性更好,部分浏览器不支持blob格式的manifest地址
  • 测试时清除浏览器缓存,避免旧manifest被缓存导致修改不生效
  • manifest中的资源路径如果是相对路径,注意和当前页面路径匹配,避免资源加载失败

内容的提问来源于stack exchange,提问作者Sharmilee S

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 16:36:03