Objective

Understand the root cause of the "A title element received an array with more than 1 element as children" warning and the error "Module not found: Can't resolve 'fs'" and eliminate both issues.

Background

As I tend to do every once in a while, I decided to upgrade to the next version of Next.js. In doing so, I expected to see new warnings and error as is typically the case when platforms change.

This time around, after upgrading to Next.js version 14.2.4 I was greeted by the following warning:

Warning: A title element received an array with more than 1 element as children. In browsers title Elements can only have Text Nodes as children. If the children being rendered output more than a single text node in aggregate the browser will display markup and comments as text in the title and hydration will likely fail and fall back to client rendering at title at head at Head ...

In short, this was happening because I was concatenating the BLOG_NAME constant with some additional text within the title element. This used to work without warning but no longer does.

import { BLOG_NAME } from '../lib/constants'
...
<Head>
  <title>{ BLOG_NAME } | About</title>
</Head>

To correct the problem I created a local function to take a string and generate a new target page title. The new title element became:

<Head>
  <title>{generatePageTitle("About")}</title>
</Head>

But of course, I wanted to reuse that function with other pages and thus I thought I'd simply move the local function to a central location with other common functions. Oddly, while initially my chosen location worked, as I continued I soon began to receive the following error:

Module not found: Can't resolve 'fs'

In researching the error I found people were trying various approaches to fixing the problem but the various solutions did not work because I did not understand what was going on.

Root Cause and Solution

And then it clicked, I was placing my function into a location that required imported modules including 'fs' that would not be available in the browser. Thus I had to isolate my new function into a location that didn't import 'fs' and other modules that would not be available when the function was called.

The new location (helpers.js) looks like this:

import { BLOG_NAME } from './constants'

export function generatePageTitle(title) {
    return BLOG_NAME + ' | ' + title;
}

And the final usage in a page looks like this:

import { generatePageTitle } from '../lib/helpers'
...

<Head>
  <title>{generatePageTitle("About")}</title>
</Head>

Helpful References