ericmatthys / nextjs-prefetch-with-rewrite Goto Github PK
View Code? Open in Web Editor NEWHome Page: nextjs-prefetch-with-rewrite.vercel.app
Home Page: nextjs-prefetch-with-rewrite.vercel.app
On the website (watch.plex.tv
), I've realized that link pre-fetching is not working so on every routing the page is fully refreshing which slows down the browse experience. I came across the Plex Engineering Medium article by chance and I found this repo also viewed the open issues on Next.js.
I forked the repo and implemented some demos with no pre-fetching issues.
Rewrites with X-Vercel-IP-Country
header: https://github.com/sinanbekar/nextjs-prefetch-with-rewrite-country
Rewrites with cookie: https://github.com/sinanbekar/nextjs-prefetch-with-rewrite-cookie
Rewrites with header (host): https://github.com/sinanbekar/nextjs-prefetch-with-rewrite
Rewrites with X-Vercel-IP-Country
header: http://nextjs-prefetch-with-rewrite-ip-country.vercel.app/
Rewrites with cookie: https://nextjs-prefetch-with-rewrite-cookie.vercel.app/
Rewrites with header (host): https://nextjs-prefetch-with-rewrite-host.vercel.app/
The errors occurred in both development and production so I don't think that is related to Vercel deployments.
Next.js rewrites with has
worked well for me except header
type. I tested the cookie
type you can see in the production demo above and there was no problem so I thought that it may be the header parsing-related issue because as we all know the cookies and custom headers are available in the same HTTP Request header (but we can't access all of them by native ways in the client-side).
Interestingly, when I specified the header key to host
it worked well except for one thing:
Client-side router behavior was different compared to server-side and it's possible because of the separated routers.
I dived a little bit deeper.
It looks like they are passing the header only with host
as a req
param to matchHas
method for the client-side router.
--continues--
// packages/next/shared/lib/router/utils/resolve-rewrites.ts#L38-L59
const handleRewrite = (rewrite: Rewrite) => {
const matcher = customRouteMatcher(rewrite.source)
let params = matcher(parsedAs.pathname)
if (rewrite.has && params) {
const hasParams = matchHas(
{
headers: {
host: document.location.hostname,
},
cookies: document.cookie
.split('; ')
.reduce<Record<string, string>>((acc, item) => {
const [key, ...value] = item.split('=')
acc[key] = value.join('=')
return acc
}, {}),
} as any,
rewrite.has,
parsedAs.query
)
.
.
.
// packages/next/shared/lib/router/utils/prepare-destination.ts#L12-L48
export function matchHas(
req: BaseNextRequest | IncomingMessage,
has: RouteHas[],
query: Params
): false | Params {
const params: Params = {}
const allMatch = has.every((hasItem) => {
let value: undefined | string
let key = hasItem.key
switch (hasItem.type) {
case 'header': {
key = key!.toLowerCase()
value = req.headers[key] as string
break
}
case 'cookie': {
value = (req as any).cookies[hasItem.key]
break
}
case 'query': {
value = query[key!]
break
}
case 'host': {
const { host } = req?.headers || {}
// remove port from host if present
const hostname = host?.split(':')[0].toLowerCase()
value = hostname
break
}
default: {
break
}
}
.
.
.
We know that there is no native way to get request headers except available in document
(host, cookies), and it seems that they don't want to pass the headers to the client-side.
https://stackoverflow.com/questions/220231/accessing-the-web-pages-http-headers-in-javascript
Except for modifying core behavior, I think cookies can be used. On every request, Next.js middleware will get the X-Vercel-IP-Country
header and set the cookie. Also, I use header type rewrite for fallback. But not sure if it is the best practice, currently works well even deleting the cookie manually. It fully refreshes and sets the cookie when the cookie does not exist then continues with prefetching. But reconsideration is needed for spoofing etc.
https://github.com/sinanbekar/nextjs-prefetch-with-rewrite-country
http://nextjs-prefetch-with-rewrite-ip-country.vercel.app/
At rewrites#header-cookie-and-query-matching, We can see that there is an example with the HTTP GET queries (searchParams) but I think there will be no problem because it does not includes a dynamic route.
// if the header `x-authorized` is present and
// contains a matching value, this rewrite will be applied
{
source: '/:path*',
has: [
{
type: 'header',
key: 'x-authorized',
value: '(?<authorized>yes|true)',
},
],
destination: '/home?authorized=:authorized',
},
I believe that there should be also a warning on the documentation.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.