Overview
A monolith is an ordinary Next app whose route trees are assembled from other
apps. withMonolith does three things when Next loads its config.
It mounts each app
For every app in the map, a symlink is written into the monolith's committed source tree:
src/app/
id/ -> ../../../id/app/
public/
id/ -> ../../id/public/
src/pages/api/
id/ -> ../../../../id/pages/api/
These are committed. They are the readable view of what the monolith is made of — GitHub renders them as links you can follow to the app they point at — and they are the input to everything else. What Next actually reads is derived from them; see Mounting.
It merges each app's config
Each app's own next.config.* is loaded and its rewrites, redirects and
headers are folded into the monolith's, with every path moved under the app's
prefix. Options that the whole deployment shares are checked rather than merged,
so an app that disagrees with the monolith stops the build instead of quietly
losing. See Routing.
It tells each app where it is
Because basePath is not used, nothing prefixes an app's own URLs for it. Each
app is told its mount through the MONOLITH_MOUNTS environment variable, which
mountPrefix and createLink
read. Unset means the app is running on its own, which is the same as being
mounted at the root — so the same code works either way.
It checks they can live together
An app that needs a newer Next than the monolith, or a different major, stops the build rather than being miscompiled — see Next versions. So does an app that disagrees about an option the whole deployment shares.
It refuses what it cannot serve
Every app's routes share one tree, so two apps cannot claim the same path. That is checked before anything is mounted — see What a monolith can serve, which also covers giving one app the site root.
What an app has to give up
An app is mounted, not deployed, so anything a deployment only gets one of
belongs to the monolith: proxy/middleware, instrumentation, pages/_app,
pages/_document, and basePath/distDir. Options like i18n and
trailingSlash have to be identical across every app, because one server serves
all of them.
This is why the monolith is recommended only for core or starter
distributions. A full or enterprise distribution should be separate
deployments. withMonolithicPortability
reports these from inside the app, before anyone tries to mount it.