Next.js 15: Unveiling the Latest Features and Performance Enhancements
Next.js 15: It's not just a version bump, it's a performance party!
Let's dive into the juicy details of these new features and see how they can spice up your web development routine.
Harnessing the Power of React 19's Innovative Hooks
Next.js 15 brings the full power of React 19 to the table, including a suite of new hooks.
Let's spotlight useActionState, a gem that simplifies managing and visualizing active actions in your UI.
const submitActionWithCurrentState = async (
prevState: any,
formData: FormData
) => {
// do some action like adding the user into the users array
};
export default function ActionStateComponent() {
const [state, formAction] = useActionState(submitActionWithCurrentState, {
users: [],
error: null,
});
return (
<div>
<h1>useActionState Example</h1>
<form action={formAction} id="action-hook-form" className="mb-4">
<div>
<input
type="text"
name="username"
placeholder="Enter your name"
/>
<button
type="submit"
>
Submit
</button>
</div>
</form>
<div>{state?.error}</div>
{state?.users?.map((user: any) => (
<div key={user.username}>
Name: {user.username} Age: {user.age}
</div>
))}
</div>
);
}
The useFormStatus keeps tabs on your forms' submission status in real-time. For instance, you can easily disable that pesky submit button while your data is zipping off to the server.
const Form = () => {
const { pending, data } = useFormStatus();
return (
<div>
<input
type="text"
name="username"
placeholder="Enter your name"
/>
<button
disabled={pending}
type="submit"
>
Submit
</button>
{pending && (
<p>Submitting {data?.get('username') as string}...</p>
)}
</div>
);
};
The useOptimistic hook Instantly update your UI with useOptimistic. This hook is ideal for optimistic updates, allowing you to provide immediate feedback to the user while the server request is still in progress.
const submitTitle = async (formData: FormData) => {
// Simulate server delay
await new Promise(resolve => setTimeout(resolve, 1000));
const newTitle = formData.get('title') as string;
if (newTitle === 'error') {
throw new Error('Title cannot be "error"');
}
return newTitle;
};
export default function OptimisticComponent() {
const [title, setTitle] = useState('Title');
const [optimisticTitle, setOptimisticTitle] = useOptimistic(title);
const [error, setError] = useState<string | null>(null);
const pending = title !== optimisticTitle;
const handleSubmit = async (formData: FormData) => {
setError(null);
setOptimisticTitle(formData.get('title') as string);
try {
const updatedTitle = await submitTitle(formData);
setTitle(updatedTitle);
} catch (e) {
setError((e as Error).message);
}
};
return (
<div>
<h1>useOptimistic Example</h1>
<h2>{optimisticTitle}</h2>
<p> {pending && 'Updating...'} </p>
<form action={handleSubmit}>
<input
type="text"
name="title"
placeholder="Change Title"
/>
<button
type="submit"
disabled={pending}
>
Submit
</button>
</form>
<div>{error && error}</div>
</div>
);
}
Enhanced Cache Mechanisms
To enhance predictability and control, Next.js 15 introduces a more granular approach to caching. Let's explore the specific changes and how to leverage them effectively.
With this, there is no more automatic caching on routes and using the inbuilt browser fetch api.
async function getData() {
const res = await fetch('https://api.dimeloper.com/', { cache: 'force-cache' });
return res.json();
}
Client-Side Routing Cache Optimization : Enhanced Client-Side Routing for Real-Time Data. To ensure optimal user experience, the default caching behavior has been modified. However, for specific use cases, manual configuration allows you to retain the previous caching mechanism.
// Next.js 15, next.config.js
module.exports = {
experimental: {
staleTimes: {
dynamic: 30, // Manually set dynamic route staleTime to 30 seconds
static: 180
},
},
};
Non-blocking, Request-Tailored (Async) APIs
Asynchronous APIs for Enhanced Performance. Request-specific APIs now leverage asynchronous operations, leading to improved performance and a more responsive user experience.
To illustrate, consider our search page, where content is rendered dynamically based on search parameters.
export default async function SearchPage({
searchParams,
}: {
searchParams: { query: string };
}) {
const params = await searchParams;
const query = params.query;
return (...)
}
领英推荐
Revolutionizing Forms: Introducing the New <Form> Component
Next.js 15's <Form> component is a game-changer for web forms. By building upon the classic HTML <form> element, it supercharges form functionality with prefetching, client-side navigation, and progressive enhancement.
export default function FormPage() {
return (
<div>
<h1>Next v15 Form Component</h1>
<p>Which saves us from a lot of boilerplate code.</p>
<Form action="/search">
{/* On submission, the input value will be appended to
the URL, e.g. /search?query=abc */}
<input
name="query"
placeholder="Enter your search query"
/>
<button
type="submit"
>
Submit
</button>
</Form>
</div>
);
}
The <Form> component offers a suite of performance and accessibility enhancements: prefetching for lightning-fast navigation, client-side navigation for a smooth user experience, and progressive enhancement for a robust fallback.
TurboPack: Supercharge Your Builds
Next.js 15 turbocharges your development workflow with TurboPack. By simply running next dev --turbo, you'll witness lightning-fast local server startups and near-instantaneous code refreshes.
For example, Vercel apps enjoy a 75% faster server boot and a 95% speedup in Fast Refresh.
To leverage this in your project, modify your development script to default to TurboPack:
"scripts": {
"dev": "next dev --turbo",
}
Static Route Flag in Development Environment
The static route indicator enhances our development workflow by providing explicit visibility into the static nature of specific routes, aiding in optimization and understanding of application behavior.
ESLint 9 Enabled
Next.js 15: Enhanced Linting for Improved Code Quality. The integration of ESLint 9 and the updated React Hooks plugin ensures robust static analysis and better adherence to best practices.
TypeScript enabled in next.config.ts
Next.js 15 introduces TypeScript support for next.config.js, enabling developers to leverage static type checking for enhanced code reliability and maintainability.
Robust Error Handling with onRequestError
Next.js 15: Elevating Observability to New Heights. The register() API unlocks deep integration with observability tools like OpenTelemetry, while Sentry's onRequestError hook provides granular insights into server-side errors.
Footnote
Next.js 15 offers a compelling suite of enhancements that can significantly elevate your web development projects.
I encourage you to explore these new features and harness their potential.