AI-preview

Migrating from Next.js 13 Page Router to Next.js 15 App Router

This week, I successfully migrated my old Next.js blog site to the latest Next.js 15 App Router. In this blog, I’ll share the challenges I faced and the steps migration process. Hopefully, this guide will help you streamline the migration of your own projects.

Let’s start with an overview of my website and how it operates with GitHub Pages.

How My Website Works

First, let me explain how my blog site operates. I’ve been developing this site for about a year, using the Next.js T3 stack to statically generate blog pages and host them for free on GitHub Pages. This approach eliminates the need for a server and ensures a fast, smooth-running site.

overview-pnp

Whenever I make changes to the data repository where my website’s content is stored, a GitHub Actions workflow is triggered. This workflow runs a build step to export a static site. The workflow’s YAML file contains all the necessary environment configurations and build steps, making it straightforward to modify or replicate.

github-action-workflow-yml

You can view my GitHub Actions workflow here.

Here are my repository

Benefits of the Upgrade

Before

image image

The older structure had some limitations:

  • Redundant code.
  • A more cluttered project directory.
  • Limited exposure to newer Next.js features.

After

image image

Next.js 15 introduces:

  • A cleaner directory structure under src/app, which centralizes pages and components.
  • Dynamic routing to manage similar pages (e.g., blogs, projects, and company pages) with less duplication.
  • Simplified setup for future changes.
  • Improved runtime performance, although the initial JavaScript load is slightly higher and requires optimization.

Directory Structure Comparison

BeforeAfter
imageimage

This new structure reduces clutter and simplifies maintenance. Any changes can now be applied in one place and reflected across all relevant pages.

Upgrading the T3 Stack

The T3 stack provides an excellent starting point for projects, including features like environment validation, Tailwind CSS, and TypeScript. To upgrade:

  1. Run the command: npm create t3-app@latest .

  2. Overwrite all files in the existing project.

  3. Compare file differences and apply the necessary updates manually.

For detailed guidance, check the T3 stack’s GitHub repository.

Migrating from Page Router to App Router

Initially, I thought migrating to the App Router would be challenging because it required reorganizing the entire directory structure under src/app. However, following the official migration documentation made the process much smoother.

SEO Enhancements

Previously, I used the next-seo library for SEO configurations. With Next.js 15, this approach has been deprecated. The new native generateMetadata function is now used for setting page titles, descriptions, and Open Graph configurations.

Here’s an example of the change:

Before:

typescript
1import { NextSeo } from 'next-seo'; 2 3<NextSeo title="Blog Title" description="Blog Description" />

After:

typescript
1export async function generateMetadata() { 2 return { 3 title: 'Blog Title', 4 description: 'Blog Description', 5 openGraph: { 6 title: 'Blog Title', 7 description: 'Blog Description', 8 }, 9 }; 10}

Bug Faced During Migration

While working on the migration, I encountered a Next.js 15 Turbo dev bug. When running npm run dev with --turbo, I received the following error when visiting the /resume page. This issue occurred because the /resume page uses react-pdf, which internally requires the canvas module. However, Next.js Turbo did not correctly detect that canvas should only be used on the client side.

typescript
1Error: ./node_modules/.pnpm/pdfjs-dist@2.15.349/node_modules/pdfjs-dist/build/pdf.js:10926:20 2Module not found: Can't resolve 'canvas' 3 10924 | class NodeCanvasFactory extends _base_factory.BaseCanvasFactory { 4 10925 | _createCanvas(width, height) { 5> 10926 | const Canvas = require("canvas"); 6 | ^^^^^^^^^^^^^^^^^ 7 10927 | 8 10928 | return Canvas.createCanvas(width, height); 9 10929 | }

After extensive research, I found a working solution. To fix this bug, update the next.config.mjs file as follows (source: react-pdf GitHub):

typescript
1const config = { 2 // Rest of the code 3 webpack: (config, { isServer }) => { 4 if (isServer) { 5 // Fix react-pdf referencing canvas in SSR 6 // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access 7 config.resolve.alias.canvas = false; 8 } 9 // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access 10 config.resolve.alias.encoding = false; 11 // eslint-disable-next-line @typescript-eslint/no-unsafe-return 12 return config; 13 }, 14 experimental: { 15 turbo: { 16 resolveAlias: { 17 canvas: "./empty-module.ts", 18 }, 19 }, 20 }, 21};

Additionally, create an empty-module.ts file in the root of the project:

typescript
1// empty-module.ts 2export default {};

This resolved the issue and allowed the /resume page to function as expected.

New Features and Improvements of My Site

Tag Feature

I introduced a dynamic tagging system to highlight my expertise with recent technologies. This feature not only improves the site’s usability but could also enhance SEO optimization.

image

Updated Homepage

I replaced the hero testimonials section with a dynamic blog section on the homepage. This adjustment prioritizes updated content and improves the chances of recent changes being indexed by search engines. Testimonials now serve as a trust-building element rather than the primary focus.

Conclusion

Upgrading to Next.js 15 was both a learning experience and a significant enhancement for my blog site. The cleaner structure, new features, and improved performance make it a worthwhile investment of time. As someone working in software development, staying updated with the latest frameworks and technologies is invaluable for tackling live product challenges and implementing new features efficiently.

If you’re planning a migration, I hope this guide helps simplify the process for you. Feel free to share your experiences or ask questions in the comments!

Post date: Dec 15, 2024, 03:23 AM
Read time: 4 min
Type: