for entries under pages folder , nextJs will not add content_hash
to entries' name. Instead the path will be__next/$nextVersion/page/$pageName.js.
As a result , each time when we make a new release , nextJs will generate a new version, and all the path of pages js will be changed and in turn the web cache is gone.
For example, if we have 10 page , and we only modify one page in next release , but all the 10 page js need to be downloaded again.
use content hash in page name
__next/$nextVersion/page/$pageName.js.
=> __next/page/$pageName_$contentHash.js
Aha~! I am planning to submit an issue like this. This is also a problem that has been bothering me for a long time.
As @wbr911 said, this wastes a lot of resources and greatly reduces development and user experience.
@timneutkens
I remember u said 「Adding hashes to page files is going to be up to us the future.」last year.#4255
Can you provide the next solution, it is very important.
Look forward to your favourable reply~~~~
It's slightly more complicated than saying "I want to add hashes", the problem space is bigger than that. For example how are you going to route? The client side is not aware of the hashes for the script tag, and it shouldn't have a list of all possible routes + hashes (that wouldn't scale).
I've just created a flow chart that (from the top of my mind) explains how the router currently works:
This issue actually comes really close to the dynamic routing one, because there needs to be a way to specify patterns to a certain page.
Adding hashes would be super simple if for example we were to do something like:
import Link, {page} from 'next/link'
export default function MyPage() {
return <>
<Link href={page`./blog/post.js`} as="/blog/hello-world">
<a>To Hello World Blog Post</a>
</Link>
</>
}
Because in that case we can compile the href into the hashed page route.
Another one that came up when thinking about this is:
import Link, {page} from 'next/link'
export default function MyPage() {
return <>
<Link href={() => import('./blog/post.js')} as="/blog/hello-world">
<a>To Hello World Blog Post</a>
</Link>
</>
}
Note that this is just me brainstorming on solutions, this is not something we're currently implementing (still thinking more about it).
Thank @timneutkens for your detailed answers, and I agree that this feature is difficult to achieve.
Maybe we have to alleviate this problem by dividing complex projects into multiple next.js apps.
@timneutkens First of All , Thanks a lot for your patient explanation
I could understand your concerns about routes
, while my architecture is MPA (multiple-pages) instead of SPA which means we don't have the routes
problems.
Could NextJs provides an alternative to add hashes to page js for MPA cases?
@wbr911 could expand on this more, do you mean you're not using next/link
and doing full page transitions?
@wbr911 could expand on this more, do you mean you're not using
next/link
and doing full page transitions?
yes @timneutkens
There is no way for us to distinguish between that, so the solution has to be generic and work for all cases.
could you let developer do it, for example to add a configuration in next.config.js to declare whether use contentHash and remove versionId in the path of page.js @timneutkens
It's not a simple as changing a configuration. We can't maintain 2 versions of page loading and building just for this one use case.
just to share my solution to people sharing same situation with us:
!isDev && (config.output.filename = '[name]_[chunkhash:8].js');
assets-webpack-plugin
to record the relationship between entry and hashed js name;_document.js
and build your own NextScript
by extending nextJs's one to replace js src with the json file created at step2So I got the custom NextScript
part working.
NextScript
is here: https://github.com/azizhk/next-typescript-mdx-emotion/compare/contenthash?expand=1But this is very much tied with implementation details of next.js and is very fragile and can break with next.js versions. I think if next.js would be open to a few changes, then just a plugin to modify the asset filename can become very easy:
NextScript
and Head
components@timneutkens if you would be ok with this I can create a PR.
Then next-plugin creators like me can easily modify the asset pathname from webpack.
Then there is the part of Link
component. Which we can create a wrapper around the original next/link
and pick the href
and map it to the correct asset path and set the correct url using asPath
(unless specified). This would be very easy.
and map it to the correct asset path and set the correct url using asPath (unless specified). This would be very easy.
Actually it's not easy, because it implies you know all routes + it doesn't account for dynamic href
or as
. Either way we're working on something to address this and it will be very different from above solution, so I would not pursue a PR for it at this point in time 🙏
Can you share your solution that you are working on or if there is a PR or a task list, maybe we can contribute?
I'm still discussing it internally before writing up something.
Ok so I got my implementation working extending NextScript and patching PageLoader.
Diff: https://github.com/azizhk/next-typescript-mdx-emotion/pull/1/files
Demo: https://5c97db3e78a9f70008989219--next-ts-mdx-emotion.netlify.com/
Posted #7329
Correct me if I'm wrong. What's the issue of storing the page->hash map on the client side and do a lookup during page transition when via Link
? I'm sure I missed something.
A middle ground IMO is to generate a BUILD ID that's a total hash of all frontend source code. This helps in my case, to not invalidate frontend cache when there's only backend changes. Do you guys think it's reasonable to do this?
@zenozen yup it's possible. I've documented the process https://medium.com/@azizhk/next-js-netlify-file-naming-and-caching-strategies-8665b213963f
Though not recommended by Next.js developers and can break in future versions of Next.js.
@azizhk Yeah, I've seen your blog post. It's really helpful!
The process sounds just right, with the asset hash mapping dictionary. But as you said, the hack is a bit too involved and likely to break when an official solution comes up. That's why I'm considering the single total hash solution and hopefully we don't have to wait long for an official solution :)
I would highly recommend not using the outlined solution, it will break for every single release we'll do, especially the ones that will be out soon.
@timneutkens Is there any update on this issue? A small change cause all js need to be downloaded again on user side seems not elegant, especially for big sites. I'm eager for the solution.
@timneutkens also asking for an update on this. Since we often have multiple deploys of the same nextjs applications per week or even per day, we are constantly invalidating caches, even from pages, that didn't change. A more user focused solution on this problem would be great.
We're making some changes soon, but will take a while as it's non-trivial to make it work. Feel free to reach out to [email protected] if you want us working on it in a shorter timeframe.
FYI - this feature was a part of v9.5 release.
Most helpful comment
It's slightly more complicated than saying "I want to add hashes", the problem space is bigger than that. For example how are you going to route? The client side is not aware of the hashes for the script tag, and it shouldn't have a list of all possible routes + hashes (that wouldn't scale).
I've just created a flow chart that (from the top of my mind) explains how the router currently works:
This issue actually comes really close to the dynamic routing one, because there needs to be a way to specify patterns to a certain page.
Adding hashes would be super simple if for example we were to do something like:
Because in that case we can compile the href into the hashed page route.
Another one that came up when thinking about this is:
Note that this is just me brainstorming on solutions, this is not something we're currently implementing (still thinking more about it).