Next.js: Where is it going, where did it come from, and what does Google have to do with it? 

It’s been almost two weeks since the Next 11 presentation. First, a little about the presentation. It was a website where, strangely enough, colored cursors were visible, and from time to time, text would appear next to them. Later it became clear that I was among other participants of this event. A decent and promising intro. Today, I'd like to talk about which technologies soon received comprehensive support, understand who helped implement them, and what goals the company was pursuing.

A few words about the technology, in case anyone managed to miss it. Next is a full-stack framework for… incremental builds, server-side rendering, static generation, or a hybrid version of React-based applications. It was developed by Zeit, a company that had the Now utility by 2016. Then, in 2020, after a $21 million investment, the company was renamed Vercel, and the Now utility (also renamed Vercel) evolved into a web service with additional functionality for deploying applications, primarily those built on Next.js, but also NuxtGatsby, Angular, and many other popular tools.

Number of next.js downloads from npm
Number of next.js downloads from npm
alt

Almost immediately after its release, Next.js became one of the most popular JavaScript backend frameworks, trailing Express.js only in a few areas

Next.js satisfaction, interest, usage, and awareness graph, according to stateofjs.com
Next.js satisfaction, interest, usage, and awareness graph, according to stateofjs.com
alt

Now, let’s briefly go back to the beginning. A few words about how it all started.

Work on Next, judging by the first commit, began on October 6, 2016, and as early as October 25, the first article describing the new framework for server-side rendering of React-based applications appeared on the zeit.co blog. Since then, active development and improvement of the framework have been underway.

In 2016, it was a framework capable of server-side rendering for pages in the pages directory (without additional libraries for routing), executing logic on the server and passing the result to the page component, adding tags to the site’s <head />, and offering simple installation and configuration. However, it did not allow for custom configurations for Webpack, Babel, styling exclusively from next/css, and much more (most of these issues were known and already planned for).

We could talk at length about all the changes in Next.js over the years - including the introduction of SSR, SSG, and ISR, the switch to TypeScript, AMP support, faster builds, and much, much more - a truly vast amount of useful functionality and improvements have been implemented. But since this article is specifically about the history of these innovations, let’s return to the present day.

Fortunately, the presentation went off without a hitch, so we were able to enjoy the event. It was kicked off, of course, by the aforementioned Guillermo Rauch, who had finished his coffee. First, we heard about the company’s results, its growing popularity in recent months, its large community, and its collaboration with Google and Facebook, as well as the importance of the developer experience and how Next worked to ensure that all changes occurred quickly while preserving all page states. This led us smoothly to the first new feature.

From practically the very beginning of Vercel’s launch, the Zeit team has placed significant emphasis on this service, adding support for new technologies and new features - analytics, app optimization, SSL, and more. Now another option has been added to this list - the very one featured in that promising intro at the beginning of the article: real-time collaboration. Share, comment on, highlight, and edit code - all directly from your browser window thanks to real-time collaboration. The Vercel team already had experience adding real-time capabilities to Next.js - specifically, when transitioning the development mode from Fetch requests to WebSockets in Next.js 8. For this new feature, Vercel chose not the classic WebSockets approach, but Replicache. The difference is that Replicache doesn’t transmit any information over WebSockets; it simply sends signals to the application indicating that a change has occurred.

It looks amazing, especially how it’s configured for responsive design.

However, it wasn’t without its share of strange glitches [tweet].

Overall, it’s a really cool tool for collaboration. It seems there’s nothing more to add here. Unless video chat is added in the corner, but that would make it an online office rather than a tool for collaborative development.

Now that the coffee had cooled slightly, Guillermo Rauch - circling an image and noting that it was too heavy - wrapped up his talk on online collaboration and handed the floor to the next speaker at the conference - Lydia Halli.

Images really do take up a significant portion of a website, not only in terms of page size but also in terms of its weight. To add optimized images to a website, the <picture /> and <source /> tags were added to HTML, along with the srcset attribute for <source /> and <img />. It was possible to create a separate component, pass different image formats and sizes into it, and receive a <picture /> element with images optimized for all screen sizes. That is, to perform two steps: compress the images and pass them to the component. However, Vercel decided to go a step further and eliminate the first step for us. Starting with version 10, Next.js can automatically compress all images; shortly after, the ability to compress them using any library of your choice was added. Additionally, the component automatically adds width and height attributes. Nevertheless, even optimized images can negatively impact metrics if they appear on the first screen. Therefore, the next innovation Lydia shared with us was a placeholder for images.

Just recently, I ran into this problem - the first image was ruining the LCP. The potential solutions were: preloading the image, loading it with high priority (which essentially means implementing lazy loading for everything else, including fonts), and loading it with a placeholder. All options were tested, and no clear improvement was noticeable in any of the approaches. It will be interesting to see the test results for Next’s solution. In any case, this solution is fully automated and will be easy to try out.

It’s worth pausing here to note how much Next values the developer experience. This thread runs from the very origins of the framework - ease of development and implementation, clear documentation, examples, and a smooth transition to new versions

The only thing that can be said about the images is that they lack out-of-the-box conversion to modern formats (WebP, JPEG 2000, JPEG XR, AVIF). Unfortunately, it’s difficult to call this feature complete just yet, but its development is certainly encouraging.

At the end of her presentation, Lydia thanked the community and Google contributors - Alex Castle and Joon Park. Google began actively participating in Next’s development in 2019, leading up to the release of Next 9. The goal of the collaboration was to improve performance and optimize built applications. The results were not long in coming, and by version 9.1.7, the results of this collaboration were already evident - a 3–8% reduction in client bundle size. In version 9.2, Alex Castle - whom we’re already familiar with - developed a new code fragmentation method that reduced the size of Barnebys’ applications by 23% (read more). Such collaborations not only help improve existing code but also assist with implementing features tailored to new services and metrics. For example, in May 2020, Google introduced a new approach to metrics - Web Vitals. Literally the very next week, the “reportWebVitals” method was added to Next.js for pages, allowing these metrics to be tracked and sent to the server or to Google Analytics. And the story doesn’t end there, because on June 15 of this year, Google introduced the “Aurora” project, aimed at collaborating with and developing open-source products. Among others, the aforementioned Alex Castle joined this team.

Now Guillermo hands the floor to Shubhie Panicker, one of the participants in the Aurora project. Google was at the forefront of modern approaches to application design, and now they are eager to share their experience and resources to make the web better together. Shubhie shares that the best approach to improving application performance is to shift as much of the optimization work as possible to frameworks, since this issue isn’t as critical for developers. One could argue with this, but the idea certainly makes sense: by abstracting away standard optimization tasks (such as image compression and font optimization), developers can tackle more complex issues, work on new ideas for improving performance, or focus on the project itself.

The first thing the "Aurora" project worked on was conformance - a tool representing a new approach to handling application errors. Essentially, it combines ESLint, TypeScript checks, and Next.js compiler errors, as well as additional rules related in one way or another to Web Vitals - such as how scripts, images, and links are added. I can’t wait to see the new way of displaying errors in Next [read more].

Overall, error handling in Next.js is a story of its own, full of changes and reworks in the pursuit of perfection. It all began with the very creation of Next.js. The first redesign of error display came as early as version 3

Then, in the fourth version, they were changed again, but the description of the error’s location was incomplete, so the next change wasn’t long in coming and appeared in the fifth version

Surprisingly, the sixth version saw no changes. However, the Vercel team realized that this approach wasn’t actually very convenient for modifications and redesigned the error display again in version 7, combining elements from the third and fifth versions.

It was a decent option and lasted all the way until Next 9.4, by the time of which it became clear that full-screen error display wasn’t all that convenient for the community

It was convenient, but still not ideal. We’d like to believe that the new option will be added soon and will stick around for a long time, because it looks much more convenient than what was done before. However, this feature is still not finished and hasn’t even been included in an official release.

Then, the floor was given to another Aurora participant - Houssein Djirdeh. First, Houssein ran the conformance check command - next lint - and we were able to see the issues affecting performance

Screenshot from the conference
Screenshot from the conference
alt

From the error messages and Houssein’s remarks, we are reminded of the importance of third-party scripts and styles for real-world business. However, while Next.js supported CSS (after Next 9.2) and Sass (after Next 9.3) with imports and modules out of the box, there were no tools for scripts. Therefore, the next topic of discussion was the <Script /> tag. An important feature of this tag is that we can not only add external scripts to the page but also specify exactly when they should load: beforeInteractive (before all app bundles are loaded), afterInteractive (after the app is hydrated), and lazyOnload (after the browser’s onload event).

Houssein then told us that 80% of websites use custom fonts. To be honest, I thought that percentage would be higher, but that’s beside the point. Often, these fonts are loaded from Google Fonts. Google has already stated that installing fonts this way is a bad idea. But people continue to use this method because it had clear advantages - it was easy to add, and once loaded, the fonts could be accessed from the cache for any site. This was possible until 2020, when Google introduced a separate cache, thereby making it unique for each site and eliminating one of the advantages. Now, Houssein presented a new approach to font optimization - inlining during the compilation of fonts loaded from Google Fonts and Adobe TypeKit - which was another useful and truly necessary innovation.

This was the last feature presented to us in the talk, but there were other interesting points as well, and here’s a brief overview of them:

Next.js 11 will use createRoot when React moves to version 18 alpha. It’s nice to see how Next.js collaborates with other tools. For example, support for Babel 7 was introduced while it was still in beta testing, and the same was true for Webpack 4 and Webpack 5Webpack 5, by the way, has been enabled by default since Next.js 10.2 (starting with Next.js 9.5, you could enable the option when Webpack was at version 5.0.0-beta.30).

The command npx @next/codemod cra-to-next is used to update an application created with CRA into a Next.js application .It was a truly interesting presentation; I heard exactly what I wanted to hear. Next has a rich history, a large community, and steady growth and development. I’m especially pleased with the involvement of the Google team, who contributed many ideas to this update and are helping to implement them.

With the release of version 10, it seemed like they had already implemented everything one could possibly think of. However, Vercel went beyond my expectations and added real-time collaboration. The new error display format (despite constant revisions) came as a surprise this time. I can’t wait to try it out, but Next hasn’t mentioned anything about it yet, and so far the discussion has only been about updating the linter for specific rules, which is also extremely useful.

Houssein concluded his part with the phrase, “We love working with great frameworks to help developers make the web faster.” The phrase “make the web faster” became the symbol of this presentation and the collaboration with Google. And I’m sure Aurora will bring us much more light.

Replies

No replies found