Next.js 12: New Features and Improvements
Next.js 12: New Features and Improvements
Next.js 12 brings significant performance improvements and exciting new features. Let's explore what's new.
Rust Compiler
Next.js 12 replaces Babel with a Rust-based compiler for faster builds.
Performance Gains
# Up to 17x faster compilation
# Up to 5x faster fresh builds
# Up to 2x faster hot module replacement
JSX Transformation
// Automatic JSX transform - no React import needed
function App() {
return <h1>Hello World</h1>;
}
// Before: import React from 'react';
// Now: Works without import
Middleware
Middleware allows you to run code before a request completes.
Basic Middleware
// middleware.js
import { NextResponse } from 'next/server';
export function middleware(request) {
// Check authentication
const isAuthenticated = request.cookies.get('token');
if (!isAuthenticated && request.nextUrl.pathname.startsWith('/dashboard')) {
return NextResponse.redirect(new URL('/login', request.url));
}
return NextResponse.next();
}
export const config = {
matcher: '/dashboard/:path*',
};
Rewrites and Headers
export function middleware(request) {
const response = NextResponse.next();
// Add custom header
response.headers.set('x-custom-header', 'value');
// Rewrite URL
if (request.nextUrl.pathname.startsWith('/old-blog')) {
return NextResponse.rewrite(new URL('/blog', request.url));
}
return response;
}
Enhanced Image Optimization
import Image from 'next/image';
// New placeholder feature
<Image
src="/hero.jpg"
alt="Hero"
width={1200}
height={800}
placeholder="blur"
blurDataURL="data:image/jpeg;base64,..."
/>
// Remote images
<Image
src="https://example.com/image.jpg"
alt="Remote"
width={500}
height={300}
/>
// next.config.js - allow domains
module.exports = {
images: {
remotePatterns: [
{
protocol: 'https',
hostname: 'example.com',
},
],
},
};
AVIF Support
// next.config.js
module.exports = {
images: {
formats: ['image/avif', 'image/webp'],
},
};
URL Imports
Import packages directly from URLs:
// import from URL
import confetti from 'https://cdn.skypack.dev/canvas-confetti';
confetti();
// next.config.js
module.exports = {
experimental: {
urlImports: ['https://cdn.skypack.dev'],
},
};
React 18 Support
Automatic Batching
function App() {
const [count, setCount] = useState(0);
const [flag, setFlag] = useState(false);
function handleClick() {
// React 18 batches these automatically
setCount(c => c + 1);
setFlag(f => !f);
// Only one re-render
}
}
startTransition
import { startTransition } from 'react';
function SearchInput() {
const [query, setQuery] = useState('');
const [results, setResults] = useState([]);
const handleChange = (e) => {
// Urgent update
setQuery(e.target.value);
// Non-urgent update
startTransition(() => {
setResults(searchResults(e.target.value));
});
};
}
Suspense
import { Suspense } from 'react';
function App() {
return (
<Suspense fallback={<Loading />}>
<DataComponent />
</Suspense>
);
}
// With lazy loading
const LazyComponent = lazy(() => import('./LazyComponent'));
function App() {
return (
<Suspense fallback={<div>Loading...</div>}>
<LazyComponent />
</Suspense>
);
}
Data Fetching Improvements
SWC and Jest
// jest.config.js
const nextJest = require('next/jest');
const createJestConfig = nextJest({
dir: './',
});
module.exports = createJestConfig({
testEnvironment: 'jest-environment-jsdom',
});
API Routes Improvements
// pages/api/user.js
export default function handler(req, res) {
res.status(200).json({ name: 'John Doe' });
}
// With middleware
export const config = {
api: {
bodyParser: {
sizeLimit: '1mb',
},
},
};
Streaming SSR
import { Suspense } from 'react';
function StreamingPage() {
return (
<div>
<h1>Streaming SSR</h1>
<Suspense fallback={<p>Loading...</p>}>
<SlowComponent />
</Suspense>
</div>
);
}
Bot-Aware ISR Fallback
// pages/blog/[slug].js
export async function getStaticPaths() {
return {
paths: [],
fallback: 'blocking', // Better for bots
};
}
TypeScript Improvements
// Better type inference
import type { GetStaticProps, NextPage } from 'next';
interface Post {
id: string;
title: string;
}
interface Props {
posts: Post[];
}
export const getStaticProps: GetStaticProps<Props> = async () => {
const posts = await getPosts();
return {
props: { posts },
};
};
const Blog: NextPage<Props> = ({ posts }) => {
return (
<ul>
{posts.map(post => (
<li key={post.id}>{post.title}</li>
))}
</ul>
);
};
export default Blog;
ESM Support
// package.json
{
"type": "module"
}
// Or use .mjs extension
// utils/helper.mjs
export function formatDate(date) {
return new Intl.DateTimeFormat('en-US').format(date);
}
Edge Runtime
// pages/api/hello.js
export const config = {
runtime: 'edge',
};
export default function handler(request) {
return new Response(JSON.stringify({ name: 'John' }), {
headers: { 'content-type': 'application/json' },
});
}
Performance Monitoring
// pages/_app.js
export function reportWebVitals(metric) {
console.log(metric);
// Send to analytics
fetch('/api/analytics', {
method: 'POST',
body: JSON.stringify(metric),
});
}
Upgrading to Next.js 12
# Update package.json
npm install next@12 react@18 react-dom@18
# Or use the upgrade CLI
npx @next/codemod@canary upgrade 12
Breaking Changes
- Minimum Node.js version: 12.22.0
- Minimum React version: 17.0.2
- Image component changes:
layoutprop replaced withstyle - Webpack 5 required: No longer supports Webpack 4
Conclusion
Next.js 12 brings significant improvements in performance, developer experience, and features. The Rust compiler, middleware, and React 18 support make it a compelling upgrade for any project.