NextJs Update from 13 to 15
Guide: Updating storefront-starter-kit
from Next.js 13 to Next.js 15
storefront-starter-kit
from Next.js 13 to Next.js 15This guide outlines the steps to upgrade storefront-starter-kit
to Next.js 15, including updating dependencies, migrating routing logic, and aligning environment variable handling to match Next.js's built-in mechanisms.
1. Update Dependencies
Begin by upgrading your dependencies to ensure compatibility with Next.js 15:
npm i next@^15 react@^18 react-dom@^18 eslint-config-next@^15
2. Aligning Environment Variables
Previous Approach: dotenv-webpack
dotenv-webpack
In older versions, your project might use dotenv-webpack
to read .env
files and make environment variables accessible in both server and client-side code. For example:
webpack: (config) => {
config.plugins = config.plugins || [];
config.plugins = [
...config.plugins,
// Read the .env file
new Dotenv({
path: path.join(__dirname, '.env'),
systemvars: true,
}),
];
return config;
},
Why Change?
-
Conflicts in Next.js 15:
Thedotenv-webpack
plugin conflicts with Next.js 15's middleware system, causing issues such as:- Middleware not functioning correctly.
- Unexpected behavior during runtime.
-
Native Next.js Support:
Next.js now provides a robust way to handle environment variables without external plugins.
New Approach: Use Next.js .env
Conventions
.env
Conventions-
Remove the
dotenv-webpack
plugin configuration fromnext.config.js
. -
Rename your
.env
variables to align with Next.js conventions:- Public Variables: Prefix with
NEXT_PUBLIC_
to make them accessible in client-side code. - Private Variables: Do not prefix with
NEXT_PUBLIC_
to restrict them to server-side code.
- Public Variables: Prefix with
Example .env
Update:
.env
Update:Before:
API_URL=https://api.example.com
SECRET_KEY=my-secret-key
After:
NEXT_PUBLIC_API_URL=https://api.example.com
SECRET_KEY=my-secret-key
Important Notes:
- Restart the development server after modifying
.env
. - Public variables (
NEXT_PUBLIC_*
) will automatically be accessible on both the client and server. - Private variables will remain server-side only.
3. Standard Routing: Replace app.render
with rewrites()
app.render
with rewrites()
In your server/index.js
, you might find routing logic like this:
server.get('/pali', (req, res) => {
app.render(req, res, '/library/entry', req.query);
});
Action: Use rewrites()
Instead
rewrites()
Instead- Remove the route from
server/index.js
. - Add a rewrite rule in
next.config.js
:
module.exports = {
async rewrites() {
return [
{
source: '/pali',
destination: '/library/entry',
},
];
},
};
4. Wildcard Dynamic Routing
For dynamic routing where all paths redirect to a specific page, replace this logic in server/index.js
:
server.get(/^(.*)$/, (req, res) => {
app.render(req, res, '/frontend/entry', {
seoUrl: req.params[0],
...req.query,
});
});
Step 1: Add Middleware
Create a middleware.js
file in the root of your project:
import { NextRequest, NextResponse } from 'next/server';
export function middleware(req) {
const pathname = req.nextUrl.pathname;
// Match all paths using a wildcard pattern
const pattern = /^(.*)$/;
if (pattern.test(pathname)) {
const url = req.nextUrl.clone();
// Set `seoUrl` parameter based on the pathname
const seoUrl = url.pathname;
url.searchParams.set('seoUrl', seoUrl);
// Preserve existing query parameters
req.nextUrl.searchParams.forEach((value, key) => {
url.searchParams.set(key, value);
});
// Rewrite the request to /frontend/entry
return NextResponse.rewrite(url);
}
return NextResponse.next();
}
Step 2: Add a Wildcard Rewrite in next.config.js
next.config.js
Update the rewrites()
function to include a wildcard rule:
module.exports = {
async rewrites() {
return [
{
source: '/pali', // Example standard route
destination: '/library/entry',
},
{
source: '/:path*', // Wildcard for all other paths
destination: '/frontend/entry',
},
];
},
};
5. Remove Legacy Code
Delete Routing in server/index.js
server/index.js
Remove any app.render
logic, including both standard routes and wildcard handlers:
server.get('/pali', (req, res) => {
app.render(req, res, '/library/entry', req.query);
});
server.get(/^(.*)$/, (req, res) => {
app.render(req, res, '/frontend/entry', {
seoUrl: req.params[0],
...req.query,
});
});
6. Test Your Application
-
Restart the Development Server
Start the app with:npm run dev
-
Verify Environment Variables
Test public and private variables:- Log
process.env.NEXT_PUBLIC_API_URL
in client-side code. - Log
process.env.SECRET_KEY
in server-side code.
- Log
-
Verify Routing
- Test
/pali
to ensure it rewrites to/library/entry
. - Test wildcard routes like
/example
to confirm they rewrite to/frontend/entry
withseoUrl
and query parameters.
- Test
Why Migrate?
Environment Variables
- Conflict Resolution: Removing
dotenv-webpack
resolves conflicts that break Middleware in Next.js 15. - Native Support: Next.js provides first-class support for
.env
handling without additional configuration.
Routing
- Deprecation of
app.render
: Next.js 15 fully adopts the App Router, making custom server routing obsolete. - Performance: Middleware operates at the edge, reducing latency for dynamic routes.
By following this guide, your storefront-starter-kit
will be fully compatible with Next.js 15, adhering to its best practices for environment variables, routing, and middleware.
Updated 11 days ago