Incrementally Adopting Next.js

Lee Robinson

Next.js has been designed for gradual adoption. With Next.js, you can continue using your existing code and add as much (or as little) React as you need. By starting small and incrementally adding more pages, you can prevent derailing feature work by avoiding a complete rewrite.

Many companies need to modernize their tech stack to reduce costs, increase developer productivity, and provide the best experience for their customers. Component-driven development has greatly improved the deployment velocity and reusability of modern codebases.

And with over 8 million downloads/month, React is the leading component-driven choice for developers. Next.js, the React framework for production, enables you to incrementally adopt React.

Motivation

In an increasingly mobile world, improving and tracking your Core Web Vitals is critical for success. Your customers are likely distributed across the world with varying internet speeds. Every second (or millisecond) of additional time spent waiting for a page to load or an action to complete could be the difference between a sale, impression, or conversion.

If you're modernizing your tech stack, you might be facing challenges like:

  • Your application has years of legacy code that is difficult to reason about and would take years (and millions of dollars) to rewrite completely.
  • Your page load times continue to increase as the size and complexity of the application grows. Simple marketing pages are as slow as the most complex pages.
  • You're trying to scale your development team, but are facing issues adding more developers into the existing codebase.
  • You have outdated CI/CD and DevOps processes, which decrease developer productivity and make it difficult to safely and reliably roll out new changes.
  • Your application is not responsive for mobile devices and it's impossible to update the global page styling without breaking other parts of the application.

You know you need to do something, but it can be overwhelming to understand where to start. By incrementally adopting Next.js, you can begin to solve the above issues and transform your application. Let's discuss a few different strategies for adopting Next.js into your existing tech stack.

Strategies

Subpath

The first strategy is to configure your server or proxy such that, everything under a specific subpath points to a Next.js app. For example, your existing website might be at example.com, and you might configure your proxy such that example.com/store serves a Next.js e-commerce store.

Using basePath, you can configure your Next.js application's assets and links to automatically work with your new subpath /store. Since each page in Next.js is its own standalone route, pages like pages/products.js will route to example.com/store/products in your application.

// next.config.js

module.exports = {
  basePath: '/store'
}

To learn more about basePath, take a look at our documentation.

(Note: This feature was introduced in Next.js 9.5 and up. If you’re using older versions of Next.js, please upgrade before trying it out.)

Rewrites

The second strategy is to create a new Next.js app that points to the root URL of your domain. Then, you can use rewrites inside next.config.js to have some subpaths to be proxied to your existing app.

For example, let's say you created a Next.js app to be served from example.com with the following next.config.js. Now, requests for the pages you’ve added to this Next.js app (e.g. /about if you’ve added pages/about.js) will be handled by Next.js, and requests for any other route (e.g. /dashboard) will be proxied to proxy.example.com.

// next.config.js

module.exports = {
  async rewrites() {
    return [
      // we need to define a no-op rewrite to trigger checking
      // all pages/static files before we attempt proxying
      {
        source: '/:path*',
        destination: '/:path*'
      },
      {
        source: '/:path*',
        destination: `https://proxy.example.com/:path*`
      }
    ]
  }
}

To learn more about rewrites, take a look at our documentation.

Micro-Frontends with Monorepos and Subdomains

Next.js and Vercel make it easy to adopt micro-frontends and deploy as a Monorepo. This allows you to use subdomains to adopt new applications incrementally. Some benefits of micro-frontends:

  • Smaller, more cohesive and maintainable codebases.
  • More scalable organizations with decoupled, autonomous teams.
  • The ability to upgrade, update, or even rewrite parts of the frontend in a more incremental fashion.

The architecture of a monorepo deployed to Vercel.

Once your monorepo is set up, push changes to your Git repository as usual and you'll see the commits deployed to the Vercel projects you've connected. Say goodbye to outdated CI/CD processes.

An example of Deployment URLs provided by a Git Integration.

Conclusion

Next.js was designed for incremental adoption into your existing tech stack. The Vercel platform makes it a collaborative experience with deploy previews for every code change, by seamlessly integrating with GitHub, GitLab, and Bitbucket.

  • Instantly preview changes locally with Fast Refresh, increasing developer productivity.
  • Push changes to create a Branch Preview, optimized for collaboration with stakeholders.
  • Deploy to production with Vercel by merging the PR. No complicated DevOps.

To learn more, read about subpaths and rewrites or deploy an example with micro-frontends.