前端前端
fabric
算法
jsBlock
styleBlock
svgBlock
工具其他
Vue、React相关
webgl
GitHub
fabric
算法
jsBlock
styleBlock
svgBlock
工具其他
Vue、React相关
webgl
GitHub
  • 1_1_nextjs项目开发
  • 1_2_nextjs项目部署
  • React
  • React使用中遇到的一些问题
  • React构建create-react-app简单说明
  • ubuntu使用
  • vue.init
  • vue.use
  • vuex源码解析
  • Vue使用中遇到的一些问题
  • vue梳理
  • watcher&&dep
  • 代码片段
  • 打包
  • 简单双向绑定
  • 纯函数

nextjs项目开发

安装

npx create-next-app@latest my-next-app

下面一些提示,选择你要的配置

添加多语言、pc/mobile

  • 多语言项目参考链接
  • 项目链接

注

参考链接中url是对应的 /en/about、/zh/about 这种,我们统一希望改成 /about,并且区分移动端和pc端,所以修改目录和中间件

详情
目录
src
 ┣ app
 ┃ ┣ mobile
 ┃ ┃ ┣ about-us
 ┃ ┃ ┃ ┣ layout.tsx
 ┃ ┃ ┃ ┗ page.tsx
 ┃ ┃ ┣ contact-us
 ┃ ┃ ┃ ┣ layout.tsx
 ┃ ┃ ┃ ┗ page.tsx
 ┃ ┃ ┣ home
 ┃ ┃ ┃ ┣ layout.tsx
 ┃ ┃ ┃ ┗ page.tsx
 ┃ ┃ ┣ news
 ┃ ┃ ┃ ┣ layout.tsx
 ┃ ┃ ┃ ┗ page.tsx
 ┃ ┃ ┣ news-detail
 ┃ ┃ ┃ ┣ layout.tsx
 ┃ ┃ ┃ ┗ page.tsx
 ┃ ┃ ┣ product-center
 ┃ ┃ ┃ ┣ layout.tsx
 ┃ ┃ ┃ ┗ page.tsx
 ┃ ┃ ┗ solution
 ┃ ┃ ┃ ┣ layout.tsx
 ┃ ┃ ┃ ┗ page.tsx
 ┃ ┣ pc
 ┃ ┃ ┣ about-us
 ┃ ┃ ┃ ┣ layout.tsx
 ┃ ┃ ┃ ┗ page.tsx
 ┃ ┃ ┣ contact-us
 ┃ ┃ ┃ ┣ layout.tsx
 ┃ ┃ ┃ ┗ page.tsx
 ┃ ┃ ┣ home
 ┃ ┃ ┃ ┣ layout.tsx
 ┃ ┃ ┃ ┗ page.tsx
 ┃ ┃ ┣ news
 ┃ ┃ ┃ ┣ layout.tsx
 ┃ ┃ ┃ ┗ page.tsx
 ┃ ┃ ┣ news-detail
 ┃ ┃ ┃ ┣ layout.tsx
 ┃ ┃ ┃ ┗ page.tsx
 ┃ ┃ ┣ product-center
 ┃ ┃ ┃ ┣ layout.tsx
 ┃ ┃ ┃ ┗ page.tsx
 ┃ ┃ ┗ solution
 ┃ ┃ ┃ ┣ layout.tsx
 ┃ ┃ ┃ ┗ page.tsx
 ┃ ┣ layout.tsx
 ┃ ┗ page.tsx
 ┣ components
 ┃ ┣ mobile
 ┃ ┃ ┣ footer
 ┃ ┃ ┃ ┗ index.tsx
 ┃ ┃ ┣ header
 ┃ ┃ ┃ ┗ index.tsx
 ┃ ┃ ┗ MobileFontScript.tsx
 ┃ ┗ pc
 ┃ ┃ ┣ footer
 ┃ ┃ ┃ ┗ index.tsx
 ┃ ┃ ┗ header
 ┃ ┃ ┃ ┗ index.tsx
 ┣ i18n
 ┃ ┣ locales
 ┃ ┃ ┣ de
 ┃ ┃ ┃ ┣ about-us.json
 ┃ ┃ ┃ ┣ contact-us.json
 ┃ ┃ ┃ ┣ home.json
 ┃ ┃ ┃ ┣ index.json
 ┃ ┃ ┃ ┣ news-detail.json
 ┃ ┃ ┃ ┣ news.json
 ┃ ┃ ┃ ┣ product-center.json
 ┃ ┃ ┃ ┗ solution.json
 ┃ ┃ ┣ en
 ┃ ┃ ┃ ┣ about-us.json
 ┃ ┃ ┃ ┣ contact-us.json
 ┃ ┃ ┃ ┣ home.json
 ┃ ┃ ┃ ┣ index.json
 ┃ ┃ ┃ ┣ news-detail.json
 ┃ ┃ ┃ ┣ news.json
 ┃ ┃ ┃ ┣ product-center.json
 ┃ ┃ ┃ ┗ solution.json
 ┃ ┃ ┗ zh
 ┃ ┃ ┃ ┣ about-us.json
 ┃ ┃ ┃ ┣ contact-us.json
 ┃ ┃ ┃ ┣ home.json
 ┃ ┃ ┃ ┣ index.json
 ┃ ┃ ┃ ┣ news-detail.json
 ┃ ┃ ┃ ┣ news.json
 ┃ ┃ ┃ ┣ product-center.json
 ┃ ┃ ┃ ┗ solution.json
 ┃ ┣ client.ts
 ┃ ┣ i18next.ts
 ┃ ┣ index.ts
 ┃ ┗ settings.ts
 ┣ styles
 ┃ ┣ mobile
 ┃ ┃ ┣ about-us.scss
 ┃ ┃ ┣ ani.scss
 ┃ ┃ ┣ comm.scss
 ┃ ┃ ┣ contact-us.scss
 ┃ ┃ ┣ footer.scss
 ┃ ┃ ┣ header.scss
 ┃ ┃ ┣ home.scss
 ┃ ┃ ┣ index-en.scss
 ┃ ┃ ┣ index.scss
 ┃ ┃ ┣ news-detail.scss
 ┃ ┃ ┣ news.scss
 ┃ ┃ ┣ product-center.scss
 ┃ ┃ ┗ solution.scss
 ┃ ┗ pc
 ┃ ┃ ┣ about-us.scss
 ┃ ┃ ┣ ani.scss
 ┃ ┃ ┣ comm.scss
 ┃ ┃ ┣ contact-us.scss
 ┃ ┃ ┣ footer.scss
 ┃ ┃ ┣ header.scss
 ┃ ┃ ┣ home.scss
 ┃ ┃ ┣ index-en.scss
 ┃ ┃ ┣ index.scss
 ┃ ┃ ┣ news-detail.scss
 ┃ ┃ ┣ news.scss
 ┃ ┃ ┣ product-center.scss
 ┃ ┃ ┗ solution.scss
 ┣ utils
 ┃ ┣ client.ts
 ┃ ┗ service.ts
 ┗ middleware.ts
中间件 middleware.ts
import { NextResponse, NextRequest } from "next/server";
import acceptLanguage from "accept-language";
import { fallbackLng, languages, cookieName, headerName } from "@/i18n/settings";
import { isMobileByUserAgent } from "./utils/service";

acceptLanguage.languages(languages);

export const config = {
  matcher: [
    // 仅匹配需要处理的非静态请求
    '/((?!api|_next/static|_next/image|assets|favicon.ico|sw.js|site.webmanifest).*)',
  ],
};

export function isLanguage(lang: string) {
  return languages.includes(lang);
}

const rewriteUrls = [
  "/about-us",
  "/contact-us",
  "/news",
  "/news-detail",
  "/product-center",
  "/solution",
];
export function middleware(req: NextRequest) {
  const pathname = req.nextUrl.pathname;
  const url = req.nextUrl.clone();

  // 静态资源直接跳过(保险起见)
  if (/\.(png|jpg|jpeg|gif|svg|ico|webp|woff2?|ttf)$/i.test(pathname) || pathname.includes('/_next/')) {
    return NextResponse.next();
  }

  // 检查 Cookie 和 Accept-Language
  let lng: string | undefined = req.cookies.get(cookieName)?.value;
  if (!lng || !isLanguage(lng)) {
    const headerLang = acceptLanguage.get(req.headers.get("Accept-Language"));
    if (headerLang && isLanguage(headerLang)) {
      lng = headerLang;
    } else {
      lng = fallbackLng;
    }
  }

  // 创建带自定义 Header 的响应
  const headers = new Headers(req.headers);
  headers.set(headerName, lng); // 设置语言 Header

  const userAgent = req.headers.get("user-agent") || "";
  const isMobile = isMobileByUserAgent(userAgent);
  const deviceDir = isMobile ? "mobile" : "pc";

  // 内部重写路径但保持URL不变
  if (rewriteUrls.some((route) => pathname.startsWith(route))) {
    url.pathname = `/${deviceDir}${pathname}`;
    const response = NextResponse.rewrite(url, { headers });
    response.cookies.set(cookieName, lng, {
      maxAge: 60 * 60 * 24 * 365,
      sameSite: "lax",
    });
    return response;
  }

  // 处理根路径 /
  if (pathname === "/") {
    url.pathname = `/${deviceDir}/home`;
    const response = NextResponse.rewrite(url, { headers });
    response.cookies.set(cookieName, lng, {
      maxAge: 60 * 60 * 24 * 365,
      sameSite: "lax",
    });
    return response;
  }

  // 其他请求处理
  const response = NextResponse.next({ headers });
  response.cookies.set(cookieName, lng, {
    maxAge: 60 * 60 * 24 * 365,
    sameSite: "lax",
  });
  return response;
}


首次加载特别慢

第一次tab切换,访问页面速度特别慢,是因为页面第一次访问时nextjs需要构建页面,那么我们可以把页面页面或组件以类似 SSG(静态生成) 的方式构建

下面是nextjs服务端三种模式

模式场景服务端构建行为页面是否实时更新用法性能
SSG只在构建时拉取数据构建时一次性生成 HTML(静态)需要重新buildexport const dynamic = 'force-static' + fetch()极快
SSR实时更新每次请求都由服务端动态生成 HTML总是更新fetch(..., { cache: 'no-store' })较慢
ISR定期更新构建时生成 HTML,后续定期自动刷新半实时(渐进更新)fetch(..., { next: { revalidate: 60 } })优
// app/pc/home/page.tsx
export const dynamic = 'force-static';

async function getData() {
  const res = await fetch('https://api.example.com/home', {
    // 为确保静态化,使用 `cache: 'force-cache'`(默认)
    // 这在构建时会执行,生成静态 HTML
  });
  return res.json();
}

export default async function Page() {
  const data = await getData();

  return (
    <main>
      <h1>{data.title}</h1>
    </main>
  );
}

警告

但是这样用不了多语言切换,放弃,在Link中加prefetch,好像也没多大作用,目前暂时没有找到好的解决方案

import Link from "next/link";
<Link
  href={item.url}
  prefetch={true}
>
  name
</Link>
Edit this page
最近更新:: 2025/5/19 16:50
Contributors: wu.hui
Next
1_2_nextjs项目部署