rewrite
vs. redirect
Let's first understand this difference.
A rewrite is something that happens on the server only. The server will rewrite the URL that has been requested and search for content of that rewritten URL. The client will not know anything about that. E.g. if /a.html is rewritten to /b.html, the client will receive the same content on both URLs. Client won't know, if there is the same file two times or if one (or both) requests have been rewritten to some other resource.
A redirect on the other hand side involves the client (i.e. browser). If the server is asked for an URL that should be redirected, it will reply back to the client/browser with the destination URL of the rewrite. The client will then send another request for the new URL and make this visible to the end user by changing the address in the navigation bar. If /a.html is redirected to /b.html, the client will not receive the actual content of b.html when requesting a.html, but the browser will update the address to b.html and send a new request.
What's the issue with rewrites in your case?
The HTML contains references to other resources using absolute paths, e.g. something like:
<script src="/_next/static/..."></script>
If this file should be served as docs.example.com
and example.com/docs
(e.g. using rewrites), the actual HTML will not change. The browser will thus try to access docs.example.com/_next/static/...
or example.com/_next/static/...
respectively. That works for the first case (docs.example.com
), but not for the second one. You've noticed that already.
You can change the basePath
of next, e.g. to /docs
. Then the HTML would contain <script src="/docs/_next/...">
. That would make the browser request docs.example.com/docs/_next/...
or example.com/docs/_next/...
respectively. That would work for the second case, but not the first one. You could heal the first case with more rewrite rules, but I'd suggest a KISS solution.
Now what?
As mentioned in the comments, placing the exact same content at two different addresses is not good practice. And you can see, that is is causing subsequent difficulties as well. (Not to mention punishment by search engines for duplicate content.)
A good solution would be to decide where to store the content. That should be either docs.example.com
or example.com/docs
, not both.
Using docs.example.com, forwarding example.com/docs/ to docs.example.com
I'd suggest (and assume in this section) to take docs.example.com
to have a clear separation of concerns.
So in Vercel you would set up two projects. One for your "main" next instance, another one for the "docs" next instance. (Both can come from the same repo, that doesn't matter.)
You then assign domains to both projects, e.g. www.example.com
to the "main" project, docs.example.com
to the "docs" project.
example.com
as well as docs.example.com
should be working right now.
example.com/docs/
should yield a 404 error.
Then you add redirects (not rewrites!) for your "main" project by adding a vercel.json
like this:
{
"redirects": [
{ "source": "/docs/:path*", "destination": "https://docs.example.com/:path*" }
]
}
Now, if you enter example.com/docs/foo
in your browser, you should be redirected to docs.example.com/foo
and the page should load properly.
Using only example.com/docs/
If you decide to have the docs content only at example.com/docs/
, the solution would be as follows:
- Add
basePath: '/docs'
to next.config.js
of the docs next project. Do not add a domain to this vercel project.
- In the "main" next project add a
vercel.json
with a rewrite like this:
{
"rewrites": [
{ "source": "/docs", "destination": "https://$domain-of-docs-project.vercel.app/docs" },
{ "source": "/docs/:path*", "destination": "https://$domain-of-docs-project.vercel.app/docs/:path*" }
]
}
Please comment, if you have additional questions or this doesn't fix the issue.