Next-js-Boilerplate渐进式迁移:从Create React App到Next.js分步指南

【免费下载链接】Next-js-Boilerplate 🚀🎉📚 Boilerplate and Starter for Next.js 14+ with App Router and Page Router support, Tailwind CSS 3.3 and TypeScript ⚡️ Made with developer experience first: Next.js + TypeScript + ESLint + Prettier + Husky + Lint-Staged + Jest + Testing Library + Cypress + Storybook + Commitlint + VSCode + Netlify + PostCSS + Tailwind CSS 【免费下载链接】Next-js-Boilerplate 项目地址: https://gitcode.com/GitHub_Trending/ne/Next-js-Boilerplate

引言:为什么要迁移到Next.js?

你还在为Create React App的性能瓶颈、SEO问题和复杂的配置而烦恼吗?随着React生态的不断发展,Next.js已经成为构建现代React应用的首选框架。本指南将带你逐步完成从Create React App到Next.js的平滑迁移,充分利用Next.js 14+的强大功能,包括App Router、服务器组件、内置优化和增强的开发体验。

读完本文,你将能够:

  • 理解Create React App与Next.js的核心差异
  • 分步实施迁移计划,最小化业务中断
  • 利用Next.js的高级特性提升应用性能和SEO
  • 优化开发流程,集成TypeScript、ESLint和测试工具
  • 解决常见迁移问题,确保平稳过渡

一、迁移前的准备工作

1.1 环境要求检查

在开始迁移前,请确保你的开发环境满足以下要求:

环境要求 版本 检查命令
Node.js >=20 node -v
npm >=8 npm -v
Git 任意稳定版 git --version
操作系统 Windows/macOS/Linux -

如果需要升级Node.js,建议使用nvm(Node Version Manager)进行版本管理。

1.2 项目评估与规划

在迁移前,对现有Create React App项目进行全面评估至关重要。创建一个迁移清单,包括:

  • 项目规模和复杂度
  • 使用的第三方库和依赖
  • 自定义配置(webpack、babel等)
  • 路由结构
  • 状态管理方案
  • API调用方式
  • 测试覆盖率

以下是一个项目评估表,可帮助你识别潜在挑战:

项目特性 现状 Next.js对应方案 迁移难度
路由管理 React Router App Router/Page Router
数据获取 客户端fetch/axios 服务器组件/SWR/React Query
状态管理 Redux/MobX/Context API React Context/Zustand/Jotai 低-中
样式方案 CSS Modules/SCSS/Styled Components Tailwind CSS/CSS Modules
构建工具 CRA内置webpack Next.js内置webpack
测试工具 Jest/React Testing Library Vitest/Playwright

1.3 创建迁移分支

为避免影响现有开发,建议在Git中创建专门的迁移分支:

# 克隆仓库
git clone https://gitcode.com/GitHub_Trending/ne/Next-js-Boilerplate
cd Next-js-Boilerplate

# 创建迁移分支
git checkout -b migrate-from-cra

二、项目结构迁移

2.1 目录结构对比

Create React App和Next.js的目录结构有显著差异,特别是在引入App Router后。以下是主要对比:

# Create React App 典型结构
src/
├── assets/          # 静态资源
├── components/      # React组件
├── pages/           # 页面组件 (通常与React Router配合)
├── services/        # API服务
├── utils/           # 工具函数
├── App.js           # 根组件
├── index.js         # 入口文件
└── routes.js        # 路由配置

# Next.js 14+ App Router结构
src/
├── app/             # App Router根目录
│   ├── [locale]/    # 国际化路由
│   │   ├── (auth)/  # 认证相关路由组
│   │   └── (marketing)/ # 营销页面路由组
│   ├── api/         # API路由
│   ├── layout.tsx   # 根布局
│   └── page.tsx     # 首页
├── components/      # React组件
├── libs/            # 工具库和配置
├── models/          # 数据模型
└── utils/           # 工具函数

2.2 核心文件迁移

2.2.1 从index.js到App Router入口

Create React App的入口文件通常是src/index.js,而Next.js 14+使用App Router时,入口是src/app/layout.tsxsrc/app/page.tsx

迁移步骤:

  1. 创建根布局文件src/app/layout.tsx
// src/app/layout.tsx
import '@/styles/global.css';
import type { Metadata } from 'next';

export const metadata: Metadata = {
  title: 'Next.js Boilerplate',
  description: '从Create React App迁移到Next.js的示例项目',
};

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="en">
      <body>{children}</body>
    </html>
  );
}
  1. 创建首页文件src/app/page.tsx
// src/app/page.tsx
export default function Home() {
  return (
    <main>
      <h1>欢迎来到Next.js应用</h1>
      {/* 迁移自CRA的首页内容 */}
    </main>
  );
}
2.2.2 路由系统迁移

将React Router迁移到Next.js App Router是迁移过程中的核心任务之一。Next.js App Router基于文件系统,使用目录结构定义路由。

关键差异对比:

功能 React Router (CRA) Next.js App Router
路由定义 JSX配置或routes.js 文件系统目录结构
动态路由 :param 语法 [param] 目录
嵌套路由 Outlet 组件 嵌套目录 + layout.tsx
路由守卫 自定义HOC或组件 中间件(middleware.ts)
代码分割 需要手动配置 自动基于路由分割

迁移示例:

CRA中使用React Router的路由配置:

// src/routes.js
import { BrowserRouter, Routes, Route } from 'react-router-dom';
import Home from './pages/Home';
import About from './pages/About';
import Contact from './pages/Contact';
import NotFound from './pages/NotFound';

function AppRoutes() {
  return (
    <BrowserRouter>
      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="/about" element={<About />} />
        <Route path="/contact" element={<Contact />} />
        <Route path="*" element={<NotFound />} />
      </Routes>
    </BrowserRouter>
  );
}

迁移到Next.js App Router:

src/
└── app/
    ├── page.tsx          # 对应 / 路由
    ├── about/
    │   └── page.tsx      # 对应 /about 路由
    ├── contact/
    │   └── page.tsx      # 对应 /contact 路由
    └── not-found.tsx     # 对应 404 路由

2.3 静态资源迁移

Next.js提供了更高效的静态资源处理方式。将CRA项目中的静态资源迁移到Next.js:

  1. public/目录下的所有文件复制到Next.js项目的public/目录。
  2. 将组件中引用的资源路径从相对路径改为绝对路径:
// CRA
import logo from './logo.svg';
<img src={logo} alt="Logo" />

// Next.js
<img src="/logo.svg" alt="Logo" />
  1. 对于需要优化的图片,使用Next.js的next/image组件:
import Image from 'next/image';

function Logo() {
  return (
    <Image
      src="/logo.svg"
      alt="Logo"
      width={120}
      height={40}
      priority // 首屏关键图片
    />
  );
}

三、依赖与配置迁移

3.1 package.json 配置迁移

对比CRA和Next.js项目的package.json,主要差异在依赖和脚本部分。以下是关键迁移步骤:

  1. 核心依赖替换
{
  "dependencies": {
    // 移除CRA依赖
    "react-scripts": "^5.0.1",
    "react-router-dom": "^6.22.0",
    
    // 添加Next.js核心依赖
    "next": "^15.5.0",
    "react": "19.1.1",
    "react-dom": "19.1.1"
  }
}
  1. 脚本命令替换
{
  "scripts": {
    // 移除CRA脚本
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    
    // 添加Next.js脚本
    "dev": "next dev",
    "build": "next build",
    "start": "next start",
    "lint": "next lint",
    "test": "vitest run",
    "test:e2e": "playwright test"
  }
}
  1. 添加TypeScript支持(如果使用):

Next.js Boilerplate已内置TypeScript支持,确保tsconfig.json配置正确:

{
  "compilerOptions": {
    "target": "ES2017",
    "lib": ["dom", "dom.iterable", "esnext"],
    "allowJs": true,
    "skipLibCheck": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "noEmit": true,
    "esModuleInterop": true,
    "module": "esnext",
    "moduleResolution": "bundler",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "jsx": "preserve",
    "incremental": true,
    "plugins": [{ "name": "next" }],
    "paths": {
      "@/*": ["./src/*"]
    }
  },
  "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
  "exclude": ["node_modules"]
}

3.2 样式方案迁移

Next.js Boilerplate使用Tailwind CSS作为主要样式方案。如果你的CRA项目使用其他样式方案,需要进行相应迁移:

3.2.1 从CSS/SCSS迁移到Tailwind CSS
  1. 安装Tailwind CSS依赖:
npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init -p
  1. 配置Tailwind CSS:
// tailwind.config.js
module.exports = {
  content: [
    "./src/**/*.{js,ts,jsx,tsx}",
  ],
  theme: {
    extend: {},
  },
  plugins: [],
}
  1. 创建全局CSS文件:
/* src/styles/global.css */
@tailwind base;
@tailwind components;
@tailwind utilities;
  1. 在根布局中导入全局CSS:
// src/app/layout.tsx
import '@/styles/global.css';

export default function RootLayout({ children }) {
  return (
    <html lang="en">
      <body>{children}</body>
    </html>
  );
}
  1. 将组件中的CSS类迁移到Tailwind类:
// CRA中的CSS Modules方式
import styles from './Button.module.css';

function Button() {
  return <button className={styles.primary}>Click me</button>;
}

// Next.js中的Tailwind方式
function Button() {
  return <button className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">Click me</button>;
}
3.2.2 保留CSS Modules(如果需要)

如果你希望继续使用CSS Modules,Next.js也提供了良好支持:

src/
├── components/
│   ├── Button.tsx
│   └── Button.module.css
// src/components/Button.tsx
import styles from './Button.module.css';

export default function Button() {
  return <button className={styles.button}>Click me</button>;
}

3.3 环境变量配置

Next.js和Create React App在环境变量处理上有所不同:

特性 Create React App Next.js
前缀 REACT_APP_* NEXT_PUBLIC_* (客户端)
服务器端变量 无特殊前缀 无前缀 (仅服务器访问)
默认环境文件 .env.development, .env.production .env.local, .env.development.local等
加载顺序 特定环境文件覆盖通用文件 更具体的环境文件覆盖一般文件

迁移步骤:

  1. 将所有REACT_APP_*前缀的环境变量重命名为NEXT_PUBLIC_*
# .env.development
# 从
REACT_APP_API_URL=http://localhost:3001/api
# 改为
NEXT_PUBLIC_API_URL=http://localhost:3001/api
  1. 对于仅在服务器端使用的变量,移除前缀:
# .env.local
# 服务器端专用变量,不会暴露给客户端
DB_CONNECTION_STRING=postgres://user:pass@localhost:5432/mydb
  1. 在代码中使用环境变量:
// 客户端组件中
console.log(process.env.NEXT_PUBLIC_API_URL);

// 服务器组件中
console.log(process.env.DB_CONNECTION_STRING);

四、核心功能迁移

4.1 页面和组件迁移

将CRA项目中的页面和组件迁移到Next.js时,需要注意以下几点:

  1. 文件扩展名:将.js.jsx文件改为.tsx(如果使用TypeScript)。
  2. 默认导出:页面组件应使用默认导出。
  3. 导入路径:利用Next.js的路径别名@/*简化导入。

迁移示例

CRA中的页面组件:

// src/pages/Home.jsx
import React from 'react';
import Header from '../components/Header';
import Footer from '../components/Footer';
import HeroSection from '../components/HeroSection';
import FeaturesSection from '../components/FeaturesSection';

function HomePage() {
  return (
    <div className="app">
      <Header />
      <main>
        <HeroSection />
        <FeaturesSection />
      </main>
      <Footer />
    </div>
  );
}

export default HomePage;

迁移到Next.js的页面组件:

// src/app/page.tsx
import Header from '@/components/Header';
import Footer from '@/components/Footer';
import HeroSection from '@/components/HeroSection';
import FeaturesSection from '@/components/FeaturesSection';

export default function HomePage() {
  return (
    <div className="min-h-screen flex flex-col">
      <Header />
      <main className="flex-grow">
        <HeroSection />
        <FeaturesSection />
      </main>
      <Footer />
    </div>
  );
}

4.2 数据获取迁移

Next.js提供了多种数据获取方式,与CRA中通常在客户端获取数据的方式有很大不同:

数据获取方式 Create React App Next.js App Router
主要位置 客户端组件 useEffect 服务器组件顶层
数据获取API fetch, axios等 fetch (扩展版), 第三方库
缓存策略 需手动实现 内置缓存和重新验证
预渲染 静态生成(SSG)和服务器端渲染(SSR)
增量静态再生 ISR (Incremental Static Regeneration)

迁移示例:客户端数据获取

CRA中使用useEffect获取数据:

// src/pages/Products.jsx
import { useState, useEffect } from 'react';

function Products() {
  const [products, setProducts] = useState([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);

  useEffect(() => {
    async function fetchProducts() {
      try {
        setLoading(true);
        const response = await fetch('/api/products');
        if (!response.ok) throw new Error('Failed to fetch products');
        const data = await response.json();
        setProducts(data);
      } catch (err) {
        setError(err.message);
      } finally {
        setLoading(false);
      }
    }

    fetchProducts();
  }, []);

  if (loading) return <div>Loading...</div>;
  if (error) return <div>Error: {error}</div>;

  return (
    <div>
      <h1>Products</h1>
      <ul>
        {products.map(product => (
          <li key={product.id}>{product.name}</li>
        ))}
      </ul>
    </div>
  );
}

export default Products;

Next.js中使用服务器组件获取数据:

// src/app/products/page.tsx
async function getProducts() {
  const response = await fetch('https://api.example.com/products', {
    next: { revalidate: 60 }, // 每60秒重新验证数据
  });
  
  if (!response.ok) {
    throw new Error('Failed to fetch products');
  }
  
  return response.json();
}

export default async function ProductsPage() {
  const products = await getProducts();
  
  return (
    <div>
      <h1 className="text-3xl font-bold mb-6">Products</h1>
      <ul className="space-y-4">
        {products.map(product => (
          <li key={product.id} className="border p-4 rounded-lg">
            {product.name}
          </li>
        ))}
      </ul>
    </div>
  );
}

4.3 API路由迁移

Create React App通常需要单独的后端服务来提供API,而Next.js内置了API路由功能:

迁移步骤:

  1. 创建API路由目录:
mkdir -p src/app/api
  1. 将CRA项目中的API逻辑迁移到Next.js API路由:

CRA项目中可能使用Express后端:

// server/routes/products.js
const express = require('express');
const router = express.Router();
const Product = require('../models/Product');

router.get('/', async (req, res) => {
  try {
    const products = await Product.find();
    res.json(products);
  } catch (err) {
    res.status(500).json({ error: err.message });
  }
});

router.post('/', async (req, res) => {
  try {
    const product = new Product(req.body);
    await product.save();
    res.status(201).json(product);
  } catch (err) {
    res.status(400).json({ error: err.message });
  }
});

module.exports = router;

迁移到Next.js API路由:

// src/app/api/products/route.ts
import { NextResponse } from 'next/server';
import { Product } from '@/models/Product';

// GET请求处理
export async function GET() {
  try {
    const products = await Product.find();
    return NextResponse.json(products);
  } catch (err) {
    return NextResponse.json(
      { error: (err as Error).message },
      { status: 500 }
    );
  }
}

// POST请求处理
export async function POST(request: Request) {
  try {
    const data = await request.json();
    const product = new Product(data);
    await product.save();
    return NextResponse.json(product, { status: 201 });
  } catch (err) {
    return NextResponse.json(
      { error: (err as Error).message },
      { status: 400 }
    );
  }
}
  1. 更新客户端API调用URL:
// 从
fetch('http://localhost:3001/api/products')
// 改为
fetch('/api/products')

4.4 认证系统迁移

Next.js Boilerplate集成了Clerk认证系统,提供了比CRA项目中通常使用的自定义认证更完善的解决方案:

迁移步骤:

  1. 安装Clerk依赖:
npm install @clerk/nextjs @clerk/localizations
  1. 在Next.js配置中添加Clerk:
// src/app/layout.tsx
import { ClerkProvider } from '@clerk/nextjs';
import { frFR } from '@clerk/localizations';

export default function RootLayout({ children }) {
  return (
    <html lang="en">
      <body>
        <ClerkProvider localization={frFR}>
          {children}
        </ClerkProvider>
      </body>
    </html>
  );
}
  1. 创建认证页面:
// src/app/(auth)/sign-in/page.tsx
import { SignIn } from '@clerk/nextjs';

export default function SignInPage() {
  return (
    <div className="flex justify-center items-center min-h-screen">
      <SignIn />
    </div>
  );
}

// src/app/(auth)/sign-up/page.tsx
import { SignUp } from '@clerk/nextjs';

export default function SignUpPage() {
  return (
    <div className="flex justify-center items-center min-h-screen">
      <SignUp />
    </div>
  );
}
  1. 创建认证保护路由:
// src/middleware.ts
import { clerkMiddleware, createRouteMatcher } from '@clerk/nextjs/server';

const isProtectedRoute = createRouteMatcher([
  '/dashboard(.*)',
  '/profile(.*)',
]);

export default clerkMiddleware((auth, req) => {
  if (isProtectedRoute(req)) {
    auth.protect();
  }
});

export const config = {
  matcher: ['/((?!.*\\..*|_next).*)', '/', '/(api|trpc)(.*)'],
};
  1. 在组件中使用认证状态:
// src/components/Header.tsx
import { UserButton, useAuth } from '@clerk/nextjs';

export default function Header() {
  const { isSignedIn } = useAuth();
  
  return (
    <header className="flex justify-between items-center p-4 border-b">
      <h1 className="text-xl font-bold">My App</h1>
      <nav>
        {isSignedIn ? (
          <UserButton />
        ) : (
          <div className="space-x-2">
            <a href="/sign-in" className="px-4 py-2">Sign In</a>
            <a href="/sign-up" className="px-4 py-2 bg-blue-500 text-white">Sign Up</a>
          </div>
        )}
      </nav>
    </header>
  );
}

五、国际化支持迁移

Next.js Boilerplate内置了强大的国际化(i18n)支持,使用next-intl库。如果你的CRA项目使用其他i18n解决方案(如react-i18next),可以按以下步骤迁移:

5.1 安装和配置next-intl

  1. 安装依赖:
npm install next-intl
  1. 创建国际化配置:
// src/libs/I18n.ts
import { getRequestConfig } from 'next-intl/server';

export default getRequestConfig(async ({ requestLocale }) => {
  // 获取请求的语言环境
  const locale = requestLocale || 'en';
  
  return {
    locale,
    messages: (await import(`../locales/${locale}.json`)).default,
  };
});
  1. 配置Next.js:
// next.config.ts
import createNextIntlPlugin from 'next-intl/plugin';

const withNextIntl = createNextIntlPlugin('./src/libs/I18n.ts');

/** @type {import('next').NextConfig} */
const nextConfig = {
  // 其他配置...
};

export default withNextIntl(nextConfig);

5.2 创建翻译文件

// src/locales/en.json
{
  "Index": {
    "welcome": "Welcome",
    "description": "This is a sample application",
    "learn_more": "Learn more"
  },
  "Button": {
    "submit": "Submit",
    "cancel": "Cancel"
  }
}

// src/locales/fr.json
{
  "Index": {
    "welcome": "Bienvenue",
    "description": "Ceci est une application exemple",
    "learn_more": "En savoir plus"
  },
  "Button": {
    "submit": "Soumettre",
    "cancel": "Annuler"
  }
}

5.3 在组件中使用翻译

// src/components/Welcome.tsx
import { useTranslations } from 'next-intl';

export default function Welcome() {
  const t = useTranslations('Index');
  
  return (
    <div>
      <h1>{t('welcome')}</h1>
      <p>{t('description')}</p>
      <button>{t('learn_more')}</button>
    </div>
  );
}

5.4 设置国际化路由

// src/app/[locale]/layout.tsx
import { NextIntlClientProvider } from 'next-intl';
import { getTranslations } from 'next-intl/server';

export default async function LocaleLayout({
  children,
  params: { locale }
}) {
  const messages = await getTranslations({ locale, namespace: 'Layout' });
  
  return (
    <html lang={locale}>
      <body>
        <NextIntlClientProvider locale={locale} messages={messages}>
          {children}
        </NextIntlClientProvider>
      </body>
    </html>
  );
}

// 生成静态参数
export function generateStaticParams() {
  return ['en', 'fr'].map(locale => ({ locale }));
}

六、测试系统迁移

Next.js Boilerplate使用Vitest和Playwright进行测试,而CRA通常使用Jest和React Testing Library。以下是迁移测试系统的主要步骤:

6.1 单元测试迁移(Jest到Vitest)

  1. 安装Vitest相关依赖:
npm install -D vitest @vitejs/plugin-react vite-tsconfig-paths @vitest/coverage-v8 jsdom
  1. 创建Vitest配置文件:
// vitest.config.mts
import react from '@vitejs/plugin-react';
import tsconfigPaths from 'vite-tsconfig-paths';
import { defineConfig } from 'vitest/config';

export default defineConfig({
  plugins: [react(), tsconfigPaths()],
  test: {
    environment: 'jsdom',
    coverage: {
      include: ['src/**/*'],
      exclude: ['src/**/*.stories.tsx'],
    },
    setupFiles: ['./src/setupTests.ts'],
  },
});
  1. 创建测试设置文件:
// src/setupTests.ts
import '@testing-library/jest-dom/vitest';
  1. 更新package.json脚本:
{
  "scripts": {
    "test": "vitest run",
    "test:watch": "vitest",
    "test:coverage": "vitest run --coverage"
  }
}
  1. 迁移测试文件:

大多数Jest测试可以直接在Vitest中运行,只需将文件扩展名从.test.js改为.test.tsx(如果使用TypeScript):

// src/components/Hello.test.tsx
import { render, screen } from '@testing-library/react';
import Hello from './Hello';

describe('Hello', () => {
  it('renders a welcome message', () => {
    render(<Hello name="John" />);
    expect(screen.getByText(/hello, john!/i)).toBeInTheDocument();
  });
});

6.2 端到端测试迁移(Cypress到Playwright)

Next.js Boilerplate使用Playwright进行端到端测试:

  1. 安装Playwright:
npm install -D playwright @playwright/test
npx playwright install
  1. 创建Playwright配置:
// playwright.config.ts
import { defineConfig, devices } from '@playwright/test';

export default defineConfig({
  testDir: './tests/e2e',
  timeout: 30 * 1000,
  expect: {
    timeout: 5000,
  },
  fullyParallel: true,
  forbidOnly: !!process.env.CI,
  retries: process.env.CI ? 2 : 1,
  workers: process.env.CI ? 1 : undefined,
  reporter: 'html',
  use: {
    baseURL: 'http://localhost:3000',
    trace: 'on-first-retry',
  },
  projects: [
    {
      name: 'chromium',
      use: { ...devices['Desktop Chrome'] },
    },
    {
      name: 'firefox',
      use: { ...devices['Desktop Firefox'] },
    },
    {
      name: 'webkit',
      use: { ...devices['Desktop Safari'] },
    },
  ],
  webServer: {
    command: 'npm run dev',
    url: 'http://localhost:3000',
    reuseExistingServer: !process.env.CI,
  },
});
  1. 创建测试文件:
// tests/e2e/homepage.spec.ts
import { test, expect } from '@playwright/test';

test('has title', async ({ page }) => {
  await page.goto('/');
  
  // 检查标题
  await expect(page).toHaveTitle(/Next.js Boilerplate/);
  
  // 检查欢迎消息
  await expect(page.getByRole('heading', { name: /welcome/i })).toBeVisible();
});

test('navigates to about page', async ({ page }) => {
  await page.goto('/');
  
  // 点击关于链接
  await page.getByRole('link', { name: /about/i }).click();
  
  // 验证导航
  await expect(page).toHaveURL(/about/);
  await expect(page.getByRole('heading', { name: /about us/i })).toBeVisible();
});
  1. 添加测试脚本:
{
  "scripts": {
    "test:e2e": "playwright test",
    "test:e2e:ui": "playwright test --ui",
    "test:e2e:report": "playwright show-report"
  }
}

七、部署与CI/CD迁移

7.1 构建流程迁移

Next.js的构建流程与Create React App有所不同:

特性 Create React App Next.js
构建命令 npm run build npm run build
输出目录 build/ .next/
静态导出 npm run build + 配置 next export (仅静态站点)
构建产物 纯静态文件 混合静态/动态文件,API路由等
构建分析 需要第三方工具 内置分析工具 @next/bundle-analyzer

迁移步骤:

  1. 更新构建脚本:
{
  "scripts": {
    "build": "next build",
    "build:analyze": "ANALYZE=true next build",
    "start": "next start",
    "export": "next export" // 仅静态站点需要
  }
}
  1. 配置构建分析(可选):
// next.config.ts
import withBundleAnalyzer from '@next/bundle-analyzer';

const withBundleAnalyzer = require('@next/bundle-analyzer')({
  enabled: process.env.ANALYZE === 'true',
});

module.exports = withBundleAnalyzer({
  // 你的Next.js配置
});

7.2 CI/CD配置迁移

Next.js Boilerplate使用GitHub Actions进行CI/CD。以下是从CRA项目迁移CI/CD配置的基本步骤:

  1. 创建GitHub Actions配置文件:
# .github/workflows/ci.yml
name: CI

on:
  push:
    branches: [ main, develop ]
  pull_request:
    branches: [ main, develop ]

jobs:
  lint:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: 20
          cache: 'npm'
      - name: Install dependencies
        run: npm ci
      - name: Run lint
        run: npm run lint

  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: 20
          cache: 'npm'
      - name: Install dependencies
        run: npm ci
      - name: Run tests
        run: npm test

  build:
    runs-on: ubuntu-latest
    needs: [lint, test]
    steps:
      - uses: actions/checkout@v4
      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: 20
          cache:.github/workflows/deploy.yml
name: Deploy

on:
  push:
    branches: [ main ]

【免费下载链接】Next-js-Boilerplate 🚀🎉📚 Boilerplate and Starter for Next.js 14+ with App Router and Page Router support, Tailwind CSS 3.3 and TypeScript ⚡️ Made with developer experience first: Next.js + TypeScript + ESLint + Prettier + Husky + Lint-Staged + Jest + Testing Library + Cypress + Storybook + Commitlint + VSCode + Netlify + PostCSS + Tailwind CSS 【免费下载链接】Next-js-Boilerplate 项目地址: https://gitcode.com/GitHub_Trending/ne/Next-js-Boilerplate

更多推荐