Skip to main content

Next.js

Next.js is a modern full-stack development framework based on React, developed and maintained by the Vercel team. It provides out-of-the-box features, including server-side rendering (SSR), static site generation (SSG), incremental static regeneration (ISR), API routes, file-system routing, etc., helping developers quickly build high-performance Web applications.

This guide will detail how to develop and deploy Next.js applications on CloudBase HTTP cloud functions, fully leveraging Next.js' full-stack capabilities.

Prerequisites

Before you begin, ensure that you have:

  • Node.js environment: Version 18.18 or higher (20.x recommended)
  • npm, yarn, or pnpm: Package manager
  • React Fundamentals: Familiarity with React component development
  • CloudBase account: Have registered a Tencent Cloud account and activated the TCB service

Environment Preparation

1. Check the Node.js version

# Check the Node.js version
node --version

# Check the npm version
npm --version

2. Create a Next.js application

If you already have a Next.js application, you can skip this step.

# Create a Next.js Application Using the Official CLI
npx create-next-app@latest my-nextjs-app

# Go to the project directory
cd my-nextjs-app

Configuration options during creation:

✔ Would you like to use TypeScript? … No / Yes
✔ Would you like to use ESLint? … No / Yes
✔ Would you like to use Tailwind CSS? … No / Yes
✔ Would you like to use `src/` directory? … No / Yes
✔ Would you like to use App Router? (recommended) … No / Yes
✔ Would you like to customize the default import alias (@/*)? … No / Yes

Recommended configuration:

  • TypeScript: Yes (Better type safety)
  • ESLint: Yes (Code quality assurance)
  • Tailwind CSS: Yes (Rapid styling development)
  • App Router: Yes (Recommended for Next.js 13+)

Application Development

1. Project Structure

Project Structure Using App Router:

my-nextjs-app/
├── app/
│ ├── globals.css # Global styles
│ ├── layout.tsx # Root layout
│ ├── page.tsx # Homepage
│ ├── api/ # API routes
│ │ └── users/
│ │ └── route.ts # /api/users endpoint
│ └── about/
│ └── page.tsx # /about page
├── components/ # Reusable components
├── lib/ # Utility functions
├── public/ # Static assets
├── next.config.js # Next.js configuration
└── package.json

2. Configure Next.js

Edit the next.config.js file to optimize for CloudBase deployment:

/** @type {import('next').NextConfig} */
const nextConfig = {
// Set the output mode to standalone to facilitate cloud function deployment
output: 'standalone',

// Disable the x-powered-by header
poweredByHeader: false,

// Compression configuration
compress: true,

// Image optimization configuration
images: {
domains: ['example.com'], // Domains for external images
unoptimized: true, // Disable image optimization in cloud function environments
},

// Environment variable configuration
env: {
CUSTOM_KEY: process.env.CUSTOM_KEY,
},

// Redirect configuration
async redirects() {
return [
{
source: '/old-path',
destination: '/new-path',
permanent: true,
},
];
},

// Headers configuration
async headers() {
return [
{
source: '/api/:path*',
headers: [
{
key: 'Access-Control-Allow-Origin',
value: '*',
},
{
key: 'Access-Control-Allow-Methods',
value: 'GET, POST, PUT, DELETE, OPTIONS',
},
{
key: 'Access-Control-Allow-Headers',
value: 'Content-Type, Authorization',
},
],
},
];
},
};

module.exports = nextConfig;

3. Create a page component

Home Page Component

Edit app/page.tsx:

import Link from 'next/link';
import { Metadata } from 'next';

export const metadata: Metadata = {
title: 'Next.js on CloudBase',
description: 'A Next.js application running on CloudBase HTTP Functions',
};

export default function HomePage() {
return (
<div className="min-h-screen bg-gradient-to-br from-blue-50 to-indigo-100">
<div className="container mx-auto px-4 py-16">
<div className="text-center">
<h1 className="text-4xl font-bold text-gray-900 mb-6">
Welcome to Next.js on CloudBase
</h1>
<p className="text-xl text-gray-600 mb-8">
This is a Next.js application running on a CloudBase HTTP cloud function.
</p>

<div className="grid grid-cols-1 md:grid-cols-3 gap-6 mt-12">
<FeatureCard
title="Server-Side Rendering"
description="Leverage Next.js SSR capability to enhance SEO and first-screen loading speed"
icon="🚀"
/>
<FeatureCard
title="API Routes"
description="Built-in API Routes feature to easily build full-stack applications"
icon=""
/>
<FeatureCard
title="Cloud-Native Deployment"
description="One-click deployment to CloudBase, enjoy elastic scaling and high availability"
icon="☁️"
/>
</div>

<div className="mt-12 space-x-4">
<Link
href="/about"
className="bg-blue-600 text-white px-6 py-3 rounded-lg hover:bg-blue-700 transition-colors"
>
Learn More
</Link>
<Link
href="/api/users"
className="bg-gray-600 text-white px-6 py-3 rounded-lg hover:bg-gray-700 transition-colors"
>
Test API
</Link>
</div>
</div>
</div>
</div>
);
}

interface FeatureCardProps {
title: string;
description: string;
icon: string;
}

function FeatureCard({ title, description, icon }: FeatureCardProps) {
return (
<div className="bg-white p-6 rounded-lg shadow-md">
<div className="text-3xl mb-4">{icon}</div>
<h3 className="text-xl font-semibold mb-2">{title}</h3>
<p className="text-gray-600">{description}</p>
</div>
);
}

About Page

Create app/about/page.tsx:

import { Metadata } from 'next';

export const metadata: Metadata = {
title: 'About Us - Next.js on CloudBase',
description: 'Learn more about Next.js and CloudBase',
};

export default function AboutPage() {
return (
<div className="min-h-screen bg-gray-50 py-16">
<div className="container mx-auto px-4">
<div className="max-w-4xl mx-auto">
<h1 className="text-3xl font-bold text-gray-900 mb-8">About Next.js on CloudBase</h1>

<div className="bg-white rounded-lg shadow-md p-8 mb-8">
<h2 className="text-2xl font-semibold mb-4">Tech Stack</h2>
<ul className="space-y-2 text-gray-700">
<li><strong>Next.js 14+</strong>: React full-stack framework</li>
<li><strong>TypeScript</strong>: type-safe JavaScript</li>
<li><strong>Tailwind CSS</strong>: utility-first CSS framework</li>
<li><strong>CloudBase</strong>: Tencent Cloud cloud-native application development platform</li>
</ul>
</div>

<div className="bg-white rounded-lg shadow-md p-8">
<h2 className="text-2xl font-semibold mb-4">Features</h2>
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
<div>
<h3 className="font-semibold mb-2">Frontend Features</h3>
<ul className="space-y-1 text-gray-700">
<li>• Server-Side Rendering (SSR)</li>
<li>• Static Site Generation (SSG)</li>
<li>• Incremental Static Regeneration (ISR)</li>
<li>• Automatic Code Splitting</li>
</ul>
</div>
<div>
<h3 className="font-semibold mb-2">Backend Features</h3>
<ul className="space-y-1 text-gray-700">
<li>• API Routes</li>
<li>• Middleware Support</li>
<li>• Database Integration</li>
<li>• Authentication</li>
</ul>
</div>
</div>
</div>
</div>
</div>
</div>
);
}

4. Create API routes

User API

Create app/api/users/route.ts:

import { NextRequest, NextResponse } from 'next/server';

// Mock user data
let users = [
{ id: 1, name: 'Alice Johnson', email: 'alice@example.com', role: 'admin' },
{ id: 2, name: 'Bob Smith', email: 'bob@example.com', role: 'user' },
{ id: 3, name: 'Charlie Brown', email: 'charlie@example.com', role: 'user' },
];

// GET /api/users - Obtain all users
export async function GET(request: NextRequest) {
try {
const { searchParams } = new URL(request.url);
const role = searchParams.get('role');

let filteredUsers = users;
if (role) {
filteredUsers = users.filter(user => user.role === role);
}

return NextResponse.json({
success: true,
data: filteredUsers,
total: filteredUsers.length,
});
} catch (error) {
return NextResponse.json(
{ success: false, error: 'Failed to fetch users' },
{ status: 500 }
);
}
}

// POST /api/users - Create a new user
export async function POST(request: NextRequest) {
try {
const body = await request.json();
const { name, email, role = 'user' } = body;

// Simple validation
if (!name || !email) {
return NextResponse.json(
{ success: false, error: 'Name and email are required' },
{ status: 400 }
);
}

// Checking whether the email already exists
const existingUser = users.find(user => user.email === email);
if (existingUser) {
return NextResponse.json(
{ success: false, error: 'Email already exists' },
{ status: 409 }
);
}

const newUser = {
id: Math.max(...users.map(u => u.id), 0) + 1,
name,
email,
role,
};

users.push(newUser);

return NextResponse.json(
{ success: true, data: newUser },
{ status: 201 }
);
} catch (error) {
return NextResponse.json(
{ success: false, error: 'Failed to create user' },
{ status: 500 }
);
}
}

Health Check API

Create app/api/health/route.ts:

import { NextResponse } from 'next/server';

export async function GET() {
return NextResponse.json({
status: 'ok',
timestamp: new Date().toISOString(),
uptime: process.uptime(),
environment: process.env.NODE_ENV || 'development',
version: process.env.npm_package_version || '1.0.0',
});
}

5. Add Middleware

Create middleware.ts (project root directory):

import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';

export function middleware(request: NextRequest) {
// Add security headers
const response = NextResponse.next();

response.headers.set('X-Frame-Options', 'DENY');
response.headers.set('X-Content-Type-Options', 'nosniff');
response.headers.set('Referrer-Policy', 'origin-when-cross-origin');

// CORS handling for API routes
if (request.nextUrl.pathname.startsWith('/api/')) {
response.headers.set('Access-Control-Allow-Origin', '*');
response.headers.set('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
response.headers.set('Access-Control-Allow-Headers', 'Content-Type, Authorization');

// Handling preflight requests
if (request.method === 'OPTIONS') {
return new Response(null, { status: 200, headers: response.headers });
}
}

return response;
}

export const config = {
matcher: [
'/((?!_next/static|_next/image|favicon.ico).*)',
],
};

Local Development

1. Install dependencies

# Install project dependencies
npm install

# or use yarn
yarn install

# or use pnpm
pnpm install

2. Start development server

# Starting Up in Development Mode
npm run dev

# Starting on a Specified Port
npm run dev -- -p 9000

3. Test the application

Access the following URL to test the application:

# Home
curl http://localhost:3000

# About Page
curl http://localhost:3000/about

# Health Check API
curl http://localhost:3000/api/health

# User API
curl http://localhost:3000/api/users

# Create a user.
curl -X POST http://localhost:3000/api/users \
-H "Content-Type: application/json" \
-d '{"name":"David Wilson","email":"david@example.com","role":"admin"}'

# Filter Users by Role
curl "http://localhost:3000/api/users?role=admin"

Deployment Configuration

1. Build the application

# Build Production Version
npm run build

# Start Up the Production Server (Local Testing)
npm start

2. Create the scf_bootstrap File

💡 Note:

  • When creating the scf_bootstrap file on windows, it is recommended to use
  • When creating the scf_bootstrap file using vscode on windows, deploying to an HTTP cloud function may result in an error: scf_bootstrap file does not exist
  • This error occurs because the script file contains Windows-style carriage returns (^M), causing Linux to fail to recognize the interpreter path correctly. This is a common issue in WSL

Create the scf_bootstrap file (with no extension) in the project root directory:

#!/bin/sh
# Set the port to 9000 (CloudBase HTTP cloud function requirement)
export PORT=9000

# Set the Node.js Environment to Production Mode
export NODE_ENV=production

# Start Up the Next.js Application
npm start

3. Set File Permissions

chmod +x scf_bootstrap

4. Optimize package.json

Ensure that package.json contains the correct script:

{
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "next lint"
},
"dependencies": {
"next": "14.0.0",
"react": "^18",
"react-dom": "^18"
}
}

5. Environment Variable Configuration

Create the .env.local file (for local development):

# Database Configuration
DATABASE_URL=your_database_url

# API Key
API_SECRET_KEY=your_secret_key

# External Service Configuration
EXTERNAL_API_URL=https://api.example.com

Deploy to CloudBase

Method 1: Deploy via the console

  1. Open the CloudBase console Access the Tencent Cloud CloudBase console

  2. Create an HTTP cloud function

    • Function Type: Selection of HTTP cloud function
    • Function Name: Enter nextjs-app (or a custom name)
    • Submit method: Select Local folder upload
  3. Configure deployment parameters

    • Function code: Select the root directory of your Next.js project
    • Runtime environment: Select Node.js 20.19 (recommended) or Node.js 18.15
    • Automatic dependency installation: Enable
    • Memory configuration: Recommended 512MB or higher
  4. Complete the deployment Click the "Create" button and wait for deployment to complete

Method 2: CLI Deployment

For details, see Deploy HTTP cloud function

Access Your Application

After successful deployment, you can refer to Accessing Cloud Functions via HTTP to set up custom domain access to the

You can test the following endpoints:

  • Root path: / - Express welcome page
  • Health Check: /health - View application status

Performance Optimization

1. Code Splitting

// Dynamically import components
import dynamic from 'next/dynamic';

const DynamicComponent = dynamic(() => import('../components/HeavyComponent'), {
loading: () => <p>Loading...</p>,
ssr: false, // Disable server-side rendering
});

export default function Page() {
return (
<div>
<DynamicComponent />
</div>
);
}

2. Image Optimization

import Image from 'next/image';

export default function OptimizedImage() {
return (
<Image
src="/hero-image.jpg"
alt="Hero Image"
width={800}
height={600}
priority // Priority loading
placeholder="blur" // Blur placeholder
blurDataURL="data:image/jpeg;base64,..." // Placeholder data
/>
);
}

3. Caching Policy

// app/api/data/route.ts
import { NextResponse } from 'next/server';

export async function GET() {
const data = await fetchData();

return NextResponse.json(data, {
headers: {
'Cache-Control': 'public, s-maxage=60, stale-while-revalidate=300',
},
});
}

Best Practices

1. Error Handling

Create app/error.tsx:

'use client';

export default function Error({
error,
reset,
}: {
error: Error & { digest?: string };
reset: () => void;
}) {
return (
<div className="min-h-screen flex items-center justify-center">
<div className="text-center">
<h2 className="text-2xl font-bold mb-4">Something went wrong!</h2>
<p className="text-gray-600 mb-4">{error.message}</p>
<button
onClick={reset}
className="bg-blue-600 text-white px-4 py-2 rounded hover:bg-blue-700"
>
Retry
</button>
</div>
</div>
);
}

2. Loading Status

Create app/loading.tsx:

export default function Loading() {
return (
<div className="min-h-screen flex items-center justify-center">
<div className="animate-spin rounded-full h-32 w-32 border-b-2 border-blue-600"></div>
</div>
);
}

3. 404 Page

Create app/not-found.tsx:

import Link from 'next/link';

export default function NotFound() {
return (
<div className="min-h-screen flex items-center justify-center">
<div className="text-center">
<h1 className="text-6xl font-bold text-gray-900 mb-4">404</h1>
<h2 className="text-2xl font-semibold mb-4">Page not found</h2>
<p className="text-gray-600 mb-8">Sorry, the page you are looking for cannot be found.</p>
<Link
href="/"
className="bg-blue-600 text-white px-6 py-3 rounded-lg hover:bg-blue-700 transition-colors"
>
Return to Home
</Link>
</div>
</div>
);
}

Frequently Asked Questions

Q: After deployment, are the page styles missing?

A: Check the following points:

  • Confirm the configuration of output: 'standalone' in next.config.js
  • Check whether the static resource path is correct
  • Verify whether the CSS files are packaged correctly

Q: Does the API route return a 404 error?

A: Common causes:

  • Check whether the API route file is named route.ts or route.js
  • Confirm that the file location is in the app/api/ directory
  • Verify whether the HTTP methods are exported correctly

Q: Application slow to start up?

A: Optimization suggestions:

  • Use output: 'standalone' to reduce the bundle size
  • Enable code splitting and lazy loading
  • Optimize images and static resources
  • Consider using ISR or SSG

Q: How to connect to the database?

A: It is recommended to use CloudBase database or other cloud databases:

// lib/database.ts
import { MongoClient } from 'mongodb';

const client = new MongoClient(process.env.DATABASE_URL!);

export async function connectToDatabase() {
if (!client.topology?.isConnected()) {
await client.connect();
}
return client.db('nextjs_app');
}

// app/api/users/route.ts
import { connectToDatabase } from '@/lib/database';

export async function GET() {
const db = await connectToDatabase();
const users = await db.collection('users').find({}).toArray();
return NextResponse.json({ data: users });
}

Q: How to handle environment variables?

A: Configure environment variables in the CloudBase console or using the .env file:

// Use environment variables in components
const apiUrl = process.env.NEXT_PUBLIC_API_URL; // Accessible on the client side
const secretKey = process.env.SECRET_KEY; // Only accessible on the server side

Summary

Through this guide, you have learned how to develop and deploy Next.js applications on CloudBase HTTP cloud functions. Next.js' full-stack capabilities combined with CloudBase's cloud-native features can help you quickly build modern Web applications.

It is recommended to further optimize application performance, add database integration, implement authentication features, etc., based on business requirements in actual projects to fully leverage the advantages of Next.js and CloudBase.