root ├── app, server only, include Server Side Render (SSR) pages and API route handlers ├── components, server/client, inclue reusable pure React Components ├── hooks, client only, inclue reusable logic work with states ├── models, server/client, represent domain data structure ├── db, server only │ ├── migrations, include database migrations │ └── seeds, define test data ├── public, client only, contains static assets ├── server,server only │ ├── middlewares, process before route handler and process returned response │ ├── repositories, operate with DB │ ├── services, process main logic │ └── route-handler-wrapper.ts, is Higher-Order Function (HOF) includes common process before or after route handler ├── services, client only, interact with remote services ├── store/context, client only, manage global states ├── types, server/client, include API contracts and common usage types ├── utils, include reusable helper functions ├── .env, server/client, include environment variables ├── .gitignore, ignore files won't be committed ├── middleware.ts, server only, is nextjs middleware entry, include middlewares from server/middlewares ├── next.config.ts, is nextjs project configuration ├── package.json, define project dependecies ├── README.md, show info about project └── tsconfig.json, typescript configuration
Environment Variable Management
all variables are defined in .env file.
variable prefix with NEXT_PUBLIC_, server/client
variable prefix withoutNEXT_PUBLIC_, server only
1 2 3 4 5 6 7
# .env
# expose for client and server NEXT_PUBLIC_CLIENT_VAR=test
# only expose for server DATABASE_URL="mysql://root:root@localhost:3306/kid-resource"
Route
nextjs use app router for routing, it follows directory hierarchy, all route/controller handlers define in app folder, it contains:
page.tsx, Page component with Server Side Render (SSR)
defined in route.tsx and must export function with http method name as handlers. recommend to use NextRequest/NextResponse that extend Request/Response.
Error Boundary in error.tsx file is only used for client component.
define a fixed Error Response and return it when expected error is raised.
use Error Boundary handle uncaught exceptions
Mixture for Server Component with Client Component
use React’s use hook to stream data with Promise from the server to client in Client Component.
use streaming to break up the page’s HTML into smaller chunks and send those chunks from the server to the client.
wrap Client component with loading component
use loading.tsx file in route directory
wrap with Suspense by manual
1 2 3 4 5 6 7 8 9 10 11 12 13 14
// Server Component part importPostsfrom'@/app/ui/posts import { Suspense } from 'react' export default function Page() { // Don't await the data fetching function const posts = getPosts() return ( <Suspensefallback={<div>Loading...</div>}> <Postsposts={posts} /> </Suspense> ) }