Next.js 12: New Features and Improvements
Next.js 12: New Features and Improvements
Next.js 12 brings a host of exciting features that significantly improve developer experience and application performance. Let's dive into the most important additions.
Rust Compiler: 5x Faster Builds
One of the biggest changes in Next.js 12 is the introduction of a new Rust-based compiler, replacing Babel for transformations.
// next.config.js
module.exports = {
// This is now enabled by default
swcMinify: true,
}
Benefits
- 5x faster fresh builds - Large codebases compile much faster
- 17x faster fast refresh - Hot module replacement is nearly instant
- Better error messages - Clearer, more actionable errors
Middleware: Edge Computing Made Easy
Middleware allows you to run code before a request completes, enabling powerful features at the edge.
// middleware.ts
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'
export function middleware(request: NextRequest) {
// Check for authentication
const isAuthenticated = request.cookies.get('auth-token')
if (!isAuthenticated && request.nextUrl.pathname.startsWith('/dashboard')) {
return NextResponse.redirect(new URL('/login', request.url))
}
// Add custom headers
const response = NextResponse.next()
response.headers.set('x-custom-header', 'custom-value')
return response
}
export const config = {
matcher: '/dashboard/:path*',
}
Use Cases for Middleware
- Authentication - Protect routes without hitting the server
- A/B Testing - Serve different content to different users
- Geo-location - Redirect based on user location
- Logging - Track requests at the edge
React 18 Support
Next.js 12 adds support for React 18 and its concurrent features.
// Enable React 18 in next.config.js
module.exports = {
experimental: {
reactRoot: true,
},
}
Automatic Batching
React 18 automatically batches state updates, even in promises and timeouts:
function handleClick() {
// These will be batched automatically
setCount(c => c + 1)
setFlag(f => !f)
// Only one re-render!
}
async function handleSubmit() {
const data = await fetchData()
// React 18 batches these too!
setData(data)
setLoading(false)
setError(null)
}
AVIF Image Support
Next.js 12 adds support for AVIF images, which are 20% smaller than WebP.
import Image from 'next/image'
export default function Gallery() {
return (
<Image
src="/hero.jpg"
alt="Hero image"
width={1200}
height={600}
format="avif"
priority
/>
)
}
Image Configuration
// next.config.js
module.exports = {
images: {
formats: ['image/avif', 'image/webp'],
},
}
URL Imports
Import packages directly from URLs without npm install:
// Import directly from a URL
import confetti from 'https://cdn.skypack.dev/canvas-confetti'
function Celebrate() {
const handleParty = () => {
confetti()
}
return <button onClick={handleParty}>Celebrate!</button>
}
// next.config.js
module.exports = {
experimental: {
urlImports: ['https://cdn.skypack.dev'],
},
}
Jest Configuration
Next.js 12 includes zero-configuration Jest support.
// jest.config.js
const nextJest = require('next/jest')
const createJestConfig = nextJest({
dir: './',
})
const customJestConfig = {
setupFilesAfterEnv: ['<rootDir>/jest.setup.js'],
testEnvironment: 'jest-environment-jsdom',
}
module.exports = createJestConfig(customJestConfig)
Writing Tests
// __tests__/components/Button.test.jsx
import { render, screen } from '@testing-library/react'
import Button from '@/components/Button'
describe('Button', () => {
it('renders with correct text', () => {
render(<Button>Click me</Button>)
expect(screen.getByRole('button')).toHaveTextContent('Click me')
})
})
Standalone Output for Docker
Simplified Docker deployments with standalone output mode.
// next.config.js
module.exports = {
output: 'standalone',
}
# Dockerfile
FROM node:16-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
FROM node:16-alpine AS runner
WORKDIR /app
COPY --from=builder /app/.next/standalone ./
COPY --from=builder /app/.next/static ./.next/static
COPY --from=builder /app/public ./public
EXPOSE 3000
CMD ["node", "server.js"]
Performance Improvements
Faster HMR
Hot Module Replacement is now significantly faster, especially in large projects:
- CSS updates - No more full page refresh for CSS changes
- Fast refresh - Preserves component state during edits
- Error recovery - Automatically recovers from syntax errors
Tree Shaking
Better dead code elimination:
// Only import what you need
import { debounce } from 'lodash-es'
// Instead of the entire library
Migration Guide
Upgrading from Next.js 11:
npm install next@12 react@latest react-dom@latest
Breaking Changes
- Minimum Node.js version is now 12.22.0
- Webpack 5 is the default (webpack 4 removed)
- Image optimization requires newer Sharp version
# Update Sharp for image optimization
npm install sharp@latest
Conclusion
Next.js 12 represents a significant leap forward for the framework. The Rust compiler alone makes the upgrade worthwhile, but middleware and React 18 support make this a must-have update for any serious Next.js project.
Next Steps
- Upgrade your existing projects to Next.js 12
- Experiment with middleware for edge computing
- Consider enabling React 18 concurrent features
Happy coding!