Closed roxizhauk closed 1 year ago
@roxizhauk from your reproduction steps it seems you are not calling revalidatePath()
with the correct pathname as it needs to math the name of the page on your filesystem e.g. app/blog/[id]/page
it should be revalidatePath(/blog/[id])
not revalidatePath(/blog/first)
Related response here https://github.com/vercel/next.js/issues/49778#issuecomment-1547028830
Note: we are investigating this behavior more and will add updates here
@roxizhauk from your reproduction steps it seems you are not calling
revalidatePath()
with the correct pathname as it needs to math the name of the page on your filesystem e.g.app/blog/[id]/page
it should berevalidatePath(/blog/[id])
notrevalidatePath(/blog/first)
Related response here #49778 (comment)
There's no way to trigger a revalidation of a specific dynamic route?
At the moment res.revalidate()
can achieve this for ISR paths, we are investigating this behavior for revalidatePath()
though.
Hi, I ended up here while looking for a way to provoke hard navigate:
/response/1234/sections/1
/response/[responseId]/layout.tsx
loads the right response and put it into a client context. The layout uses "force-dynamic".So I changed the router.push
to window.location.href
to provoke a refresh but that's not very good. I might instead create an endpoint to get fresh data from the client but that kinda defeats the purpose of the RSC.
Is this what you tried to achieve @roxizhauk?
All those revalidate
method seems to target static/ISR, to invalidate the server cache, but I struggle to find a solution to provoke hard navigates client-side after an update, telling to router.push("/response/1234")
that response "1234" has been modified since the page was loaded.
@eric-burel I don't think it is. What I'm trying to do here is on-demand ISR for dynamically generated static pages.
I just quickly built a simple mock with your routing and timing function that I used for my repo but it properly changes the time both on layout and pages. It's weird that your layout isn't updated even with export const dynamic = "force-dynamic"
I think you should post the issue with a repo.
Same issue with revalidate path. The path I'm trying to revalidate is like ==> [ws]/blogs/[id]. Also, if I use GET for revalidate I get 405 and If I use POST, it won't be any error. However, in your docs, you suggest using GET for on-demand re-validation. https://nextjs.org/docs/app/api-reference/functions/revalidatePath
@ijjk Hi, is the revalidatePath function designed to be revalidating an individual path or the route?
We are experiencing the same issue. Using the examples above:
App Router
revalidatePath("/blog/[id]")
-> works locally (pnpm build && pnpm start), but does not work on Vercel preview or production deployments.
revalidatePath("/blog/first")
-> does not work
Pages Router
await res.revalidate("/blog/first");
-> works locally and on Vercel
Same problem here. Event though the revalidation is not working for /en/foo/bar/
nor [lang]/[[...slug]]/
How should I revalidation from the url if my entire site's route is dynamic? app/[lang]/[[...slug]]/page
I thought maybe https://domain.com/api/revalidate?path=/foo-bar
but it doesn't revalidate.
I have the revalidation code in pages, but I tried in app, but none worked.
I also have a middleware, as I have different domain names, like domain.it and domain.fr etc.
My code:
export async function getPageByUrl(slug: string[]) {
try {
const path = (typeof slug === 'undefined' || slug[0] === 'index') ? '' : slug.join('/');
const res = await fetch(`https://domain.com/api/posts?url=/${path}`)
return await res.json();
} catch (error) {
console.log(error);
return { notFound: true };
}
}
export async function generateStaticParams() {
return [];
}
export default async function Page({
params
}: {
params: {
slug: string[]
}
}) {
const slug = params.slug;
const [PAGE] = await Promise.all([getPageByUrl(slug)]);
return (
<div className='container'>
<div dangerouslySetInnerHTML={{__html:PAGE[0].body}}></div>
</div>
)
}
@levipadre The way I handled this was with a tag in the fetch with the slug of the page.
With your fetch tagged, you can pass that as the url
parameter to the revalidate API call.
I worked with another dev on the project to discover this, so if you're interested in why it works this way:
Firstly, it's worth noting that revalidatePath
actually just calls revalidateTag
(file here). So rather than differentiating between them, let's stick with tag
for everything.
Next is caching your fetch responses on the filesystem inside .next/cache/fetch-cache
. There are a bunch of generated JSON files which are the fetch responses themselves, and then a manifest which maps a tag to a JSON filename
Checking this manifest, you'll see that it's not actually caching against the slugs of your pages, but against the filesystem path (the one with dynamic segements in it). As an example, here's an excerpt from mine:
"/[locale]/[[...slug]]/page": {
"keys": [
"97579d80f5605b49cad029b3856c33395a948fe95d061a2209d11bc4eedd98ee",
"df56bce481a809756e395b558faf3f902327952b220f7c5b39b16c86518bb769"
]
},
Calling revalidate against a specific slug (like /my-page
) won't revalidate anything because that key isn't in the manifest.
You can see there are various keys under a dynamic segment route, and these relate to how many slugs have been hit for that route. E.g. my first key is for /en/my-page
and the second for /en/my-second-page
.
I could revalidate /[locale]/[[...slug]]/page
, but then every single one of my pages' fetch calls will be revalidated, which isn't ideal when you just want to do one page. That's why adding a custom tag and revalidating against that worked well for us.
Thank you for the explanation @sdjnes. I did check the manifest in fetch-cache and I saw two tags: "tags":["/[lang]/[[...slug]]/page","/[[...slug]]/page"]
, so I tried domain.com/api/revalidate?tag=/[lang]/[[...slug]]/page
which didn't revalidate, but /api/revalidate?tag=/[[...slug]]/page
did revalidate.
So yes, I assume it revalidated all pages in this case. I have a few thousand pages generated, so obviously, I don't want to revalidate all of them.
The only thig that I don't understand, that if I add a tag to my fetch, like this:
export async function getPageByUrl(slug: string[]) {
try {
const path = (typeof slug === 'undefined' || slug[0] === 'index') ? '' : slug.join('/');
const res = await fetch(`https://domain.com/api/posts?url=/${path}`, {
next: {
tags: ['posts'],
}
})
return await res.json();
} catch (error) {
console.log(error);
return { notFound: true };
}
}
and I call domain.com/api/revalidate?tag=posts
, it's still going to revalidate all the pages, right?
What I would like to do is to revalidate only one page. There is a headless CMS, and all the data comes from a restAPI. When an editor modifies a page (e.g. https://domain.com or https://domain.com/foo or https://domain.com/foo/bar etc.), I would like to update the content on this page. Same situation when someone creates a new page or deletes one.
Is there any way to do that? Maybe dynamically add tags to all pages based on their path?
You can use the slug as the tag. This is how ours looks:
const slugString = `/${slug.join('/')}`;
...
next: {
tags: [
slugString === '/' ? '/homepage' : slugString,
]
}
...
The edge-case for the homepage is because calling revalidateTag('/')
will revalidate everything in the cache, which is obviously not what we want to do.
Then, in our CMS, we have an onUpdate hook that calls the frontend with the slug of the page (with the logic to handle the homepage edge case) -- something like /api/revalidate?tag=/my-cms-page
Wow, thank you so much @sdjnes . You are a lifesaver! It works like a charm.
You have already helped a lot, but if you don't mind, I would like to ask one more thing. Also cache related, and it seems you know your way around this topic.
My menu is acting weird cache-wise. The menu also generated by json and however I added a tag to it, it just doesn't want to cache it. Whenever I change the menu data, it refreshes immediately.
The menu is in a header, which is a client component. My code look like this:
export async function getMenu() {
try {
const res = await fetch(`https://domain.com/api/menu`, {
next: {
tags: ['menu'],
}
})
return await res.json();
} catch (error) {
console.log(error);
return { notFound: true };
}
}
the header
"use client";
import Container from 'react-bootstrap/Container';
import Nav from 'react-bootstrap/Nav';
import Navbar from 'react-bootstrap/Navbar';
import Link from 'next/link';
import React, { useEffect, useState } from 'react';
import { getMenu } from '@/lib/APIs/menu';
import { use } from 'react';
const dataPromise = getMenu();
const Header = () => {
const MENU = use(dataPromise);
return (
// use ClientOnly to prevent hydration mismatch
<ClientOnly>
<header>
<Navbar>
<Container>
<Link href='/'>Logo</Link>
<Navbar.Collapse>
<Nav>
{MENU.map((item: any) => {
return (
<Nav.Item key={item.id}>
<Link href={item.url} prefetch={false}>{item.title}</Link>
</Nav.Item>
);
})}
</Nav>
</Navbar.Collapse>
</Container>
</Navbar>
</header>
</ClientOnly>
);
}
export default Header;
export default function ClientOnly({ children }: { children: React.ReactNode }) {
const [canRender, setCanRender] = useState(false);
useEffect(() => {
setCanRender(true);
}, []);
if (!canRender) return null;
return <>{children}</>;
}
and I just import to the layout.
Can I cache the same way as the posts?
@levipadre - the above is related to this issue. If you need help with something else there are loads of other places to do so. This issue's comments should be kept on topic to avoid confusion and therefore extra effort for the maintainers.
Yes, it's true, I understand. I took a shot. Thanks anyway
Doing some further testing, I noticed an issue. I don't know if it's only my code or generic, but when I revalidate /foo
page, it also revalidates /foo/bar
page too.
By checking .next/cache/fetch-cache
, I saw that every tag does contain my generated tags, but it also contains a tag too (not by me), which is the same in every file.
E.g.:
"tags":["/foo","/[[...slug]]/page"]
and
"tags":["/foo/bar","/[[...slug]]/page"]
...so I assume because of the common /[[...slug]]/page"]
tag whenever I call a revalidation it revalidated every pages.
This is actually pretty critical - Essentially the previous res.revalidate
supported this functionality.
To allow for dynamic revalidation, I tried to use a /pages/api
endpoint to revalidate a dynamic path located in my app directory, however, this also fails because (https://github.com/vercel/next.js/issues/48771) res.revalidate
requires getStaticProps, which the app directory does not use anymore.
This means that effectively there's no way to revalidate dynamic paths in the app directory. You can use the tag revalidation, but that is only compatible with fetch
. Use cases where data is fetched directly from a database can therefore not make use of on-demand revalidation for dynamic paths.
This means that we have two options: a) Move all routes to the pages directory or b) Use a sub-optimal revalidation strategy where you (e.g.) invalidate ALL blogpost [ids] versus just id 1 when id 1 changes.
Both seem sub-optimal
Is there any possibility of adding tag as a const in the page functions. So instead of cache tags only working in fetch requests, it could work for any type of data fetching (E.g. using Prisma)
Example if we have app/[id]/page.tsx
export default async function Post(params:{id:string}){
const TAG = params.id
const post = await prisma.post.findUnique({
where: {
id: params.id
}
}
That way, we could invalidate whichever data fetching strategy is being used (be it fetch
or directly from database or whichever)
for me, res.revalidate
still works on dynamic routes created in the app directory, but not if middleware gets in the way, as described in https://github.com/vercel/next.js/issues/50464 I'm also not using standard fetch requests, so your tagging proposal looks critical indeed @SSardorf
Okay - Seems like we can use unstable_cache
to achieve the same functionality as fetch tag invalidation, but for any type of data fetching.
import { unstable_cache } from 'next/cache'
export default async function post({
postId
}: {
postId:string
}) {
const posts = await unstable_cache(
async () => {
return prisma.post.findUnique({
where: {
postId: postId,
}
})
},
[postId],
{ tags: [postId] }
)()
Then you can invalidate the post by invalidating the postId as a tag like so:
revalidateTag(postId)
Hi,
We have recently pushed couple of ISR related fix in Next.js version 13.4.5. Could you try and let us know how it goes?
@swarnava no change for me, same issues as before
As I mentioned before, revalidation is working for me (App Router API), but not how it should. It revalidates not only the given tag (path in my case) but also every child's path as well.
https://github.com/vercel/next.js/issues/49387#issuecomment-1583353332
Would it be a crazy idea not to add anything to tags by default so that the developer could decide entirely?
If I want to revalidate "/foo"
I add foo and not worry about "/foo/bar"
etc. because my structure "/[[...slug]]/page"
is included by default. If someone wants to revalidate every page, they can still add "/[[...slug]]/page"
as a tag.
We have a website coupled to a headless cms and almost all of our pages are in a catchall route. app/[[...slug]]. Some are static prebuild with generateStaticParams. With revalidatePath it looks like I can only revalidate /[[...slug]] , which would basically invalidate almost every page in the website. This is working, however it seems to me if we could invalidate a single page this would be more efficient?
We use App directory, and as previous commenter, we also use [[...slug]] for all pages, and need re-validate just some pages by path. Any solutions?
Seemingly reavalidatePath
has yet to function as we expected, even in the latest version 13.4.7-canary.1
. Should I update the repo with it?
@roxizhauk I would say yes - always good to have an updated reproduction with the latest version.
If you could make a demo on CodeSandbox or StackBlitz this can also make it easier for others to set up the environment to see the problem, confirm the behavior and try out fixes
Trying for 7 days to make this revalidatePath API route work. Everything works perfectly fine, when fetching the data from a CMS like Sanity. When publishing, saving changes on a dynamic page or blog post I get to see status code 200 and and the updated values from the console log and log file itself. However, when I refresh a page or a post I don't see any changes at all. I am not using a CDN have tested my env variables, logged all possible constants nothing is undefined or empty. But no luck.. I have to manually re-build my app in order to see the changes.
Same problem for me... Webhook is triggered but content and pages are not updated.
@Galanthus Out of curiosity, on Vercel, are you trying this on the main branch, or a Preview branch?
(only asking cos I was struggling with it too, but managed to narrow it down to the Preview environments - it works on the Production one)
@indeox Thank you for the reply. I have manually deployed my repository from my vscode terminal to production on Vercel. Previewing documents when editing pages, posts work just perfectly fine. console logging all the constants, env variables non is emtpy or undefined. When testing locally with a webhook URL to my NGROK/Expose and console log the data I get to see a status code of 200, the updated content in JSON format but refreshing that specific page doesn't do anything. GenerateStaticParams
Is not triggered again when updating and firing the hook.
@Galanthus Ah right, maybe something else then.
However as far as I know, generateStaticParams()
does not get triggered again when revalidatePath
is called. It just invalidates the cache and then only rebuilds the page upon request.
@indeox After refactoring my API and multiple code parts for days. I have finally figured it out. Since Next 13 there is no option to set fallback: true
like we would do in previous version. Instead you have to to set export const dynamic = "auto"
to each dynamic route in order to make it work after saving/publishing a post or page in order to re-generate the static file.
@indeox After refactoring my API and multiple code parts for days. I have finally figured it out. Since Next 13 there is no option to set
fallback: true
like we would do in previous version. Instead you have to to setexport const dynamic = "auto"
to each dynamic route in order to make it work after saving/publishing a post or page in order to re-generate the static file.
Auto is the default option though, I don't think you have to set it explicitly. Can you elaborate what the problem was if you didn't set dynamic to auto?
@indeox After refactoring my API and multiple code parts for days. I have finally figured it out. Since Next 13 there is no option to set
fallback: true
like we would do in previous version. Instead you have to to setexport const dynamic = "auto"
to each dynamic route in order to make it work after saving/publishing a post or page in order to re-generate the static file.Auto is the default option though, I don't think you have to set it explicitly. Can you elaborate what the problem was if you didn't set dynamic to auto?
That's what I thought removing the auto stops the revalidate function from working. It won't re-generate my static file.
The problem is that revalidatePath didn't work at all before including the dynamic option even if by default enabled.
Just removed to test if it works with export const dynamic = "auto"
and result is my page is not re-created.
@indeox After refactoring my API and multiple code parts for days. I have finally figured it out. Since Next 13 there is no option to set
fallback: true
like we would do in previous version. Instead you have to to setexport const dynamic = "auto"
to each dynamic route in order to make it work after saving/publishing a post or page in order to re-generate the static file.Auto is the default option though, I don't think you have to set it explicitly. Can you elaborate what the problem was if you didn't set dynamic to auto?
Yes, that's what I thought as well.
In my case I just set export const revalidate = 3600;
(1 hour TTL), and then just call revalidatePath
whenever there's a change from the CMS.
Yes, that's what I thought as well.
In my case I just set
export const revalidate = 3600;
(1 hour TTL), and then just callrevalidatePath
whenever there's a change from the CMS.
In my case setting export const revalidate = 3600 and removing the dynamic auto won't work anymore. Really not sure why this is the case for my code.
import { draftMode } from "next/headers"
import { notFound } from "next/navigation"
import { getAllPosts, getPage, getPageMeta, token } from "@/lib/sanity/sanity.helpers"
import { postSingleQuery } from "@/lib/queries"
import { PreviewExit } from "@/components/previews"
import { PostPageLayout } from "@/components/layout"
import { Post } from "@/models/documents/post"
import { PreviewProvider } from "@/context"
export const generateMetadata = async ({ params }: { params: { slug: string } }) => {
const page = await getPageMeta({
type: "post",
slug: params.slug
})
return page
}
export const generateStaticParams = async () => {
const posts = await getAllPosts<Post[]>("post")
return posts.map((post) => ({
slug: post.slug.current
}))
}
// export const dynamic = "auto"
// Revalidate every hour or revalidate on request.
export const revalidate = 3600
const BlogPost = async ({ params }: { params: { slug: string } }) => {
const preview = draftMode().isEnabled ? { token } : undefined
const post = await getPage<Post>(postSingleQuery, params.slug)
if (!post) {
notFound()
}
if (preview) {
return (
<PreviewProvider token={preview.token!}>
<PostPageLayout post={post} slug={params.slug} />
<PreviewExit />
</PreviewProvider>
)
}
return <PostPageLayout post={post} />
}
export default BlogPost
Sorry if I am misunderstanding, but are you now calling revalidatePath
on dynamically generated routes /posts/1
, /posts/2
, etc. or do we still need to put the path /posts/[id]
Also, a general question about ISR: How do people deal with deleting specific routes when the content is deleted from CMS?
Sorry if I am misunderstanding, but are you now calling
revalidatePath
on dynamically generated routes/posts/1
,/posts/2
, etc. or do we still need to put the path/posts/[id]
Also, a general question about ISR: How do people deal with deleting specific routes when the content is deleted from CMS?
Ask general questions somewhere like the community Discord - not this Issue which is about a specific topic.
@lukepearce Sorry, this is not general question of someone looking for help, but a specific inquiry about which revalidation strategy is being pursued in this thread. I've been following this for some time now, and anxious for revalidation methods to work according to specs, which is precisely what this issue is about, or?
I can confirm that I've lost brain cells on this as well. Recap of the above posts in this thread is that right now is that there is no way to bust cache for a specific page.
revalidatePath
only works with "router paths" and not URIs, like the old one worked. Meaning /test
and /test/[slug]
work but /test/1
doesn't. The caveat being, of course, that /test/[slug]
is a wildcard revalidate which ain't very useful.
Tagging works as an alternative, but it is only supported by next's fetch
, meaning that we can't tag stuff freely. Some people have used unstable_cache
function to tag async calls. The caveat being that it is meant for cache control over individual async actions, not whole pages, meaning we have to invent tag naming conventions ourselves.
There is no clear answer on how generateStaticParams
cache is handled. We have confirmed that unstable_cache
with tags doesn't seem to do anything within generateStaticParams
, probably due to the way the router works. @jwalcher
If one is brave or desparate and still choses to do the tagging, I would say it is in fact the most correct way of doing this as it is basically what revalidatePath
is doing as well. Unfortunately it is not a stabile API, it is entirely undocumented, not pretty to look at, and very implicit in usage, and finally, it doesn't just invalidate the tag - it caches the data, meaning it performs data transformations, and there are other GithHub issues open about those being inaccurate. 😭
For reference, for future readers, attaching an example of how I do that currently:
export default async function Post({ params }: { params: { slug: string } }) {
const post = await unstable_cache(
async () => await Posts.get(params.slug), [], {
tags: [`Posts.get-${params.slug}`]
})();
return <>Hello {post.name}</>;
}
// Elsewhere
revalidateTag(`Posts.get-${params.slug}`);
revalidateTag(`Posts.all`);
So, there effectively is no way to exert control over cache invalidation. Which was supposed to be the strongest point of the App router performance...
Thanks for the excellent summary! The lack of documentation of these issue is a bit surprising. Like, if I did not have a working revalidation with the old method, I would probably not get it running now. Will give the tags a try though.
@jwalcher Absolutely agree. It is kind of weird that Next, a framework known for championing caching stuff into the mainstream, released a version that just glosses over the whole caching thing, in a release that was supposed to be all about caching :D
How is it working for you right now? Via pages router? Can you tell us a bit more please, I would find it very useful, as am sure will others.
I guess you are using the pages router??
export default async function handler(
_req: NextApiRequest,
res: NextApiResponse,
) {
await res.revalidate(`/test`);
await res.revalidate(`/test/slug`);
return res.json({ revalidated: true });
}
Yes, I have a route handler in the pages directory calling res.revalidate on individual routes which themselves are in the app directory. I even had a workaround to revalidate also in dev mode by simply clearing the cache altogether
pages/api/revalidate.ts
const directory = process.cwd() + "/.next/cache/fetch-cache";
export default async function handler(req: NextApiRequest, res: NextApiResponse<Data>) {
if (process.env.NODE_ENV === "development") {
console.log("clearing cache");
fs.readdir(directory, (err, files) => {
for (const file of files) {
fs.unlink(path.join(directory, file), (err) => { if (err) throw err; });
}
});
return res.json({ cacheCleared: true });
} else {
const pathsToRevalidate = revalPaths(req.body);
console.log("revalidating", pathsToRevalidate);
// The argument of res.revalidate should be the path of the actual route not a rewritten or
// dynamically generated one, e.g. for "/blog/[slug]" this should be "/blog/post-1"
await Promise.all(pathsToRevalidate.map((path) => res.revalidate(path)));
return res.json({ revalidated: true });
}
}
This strategy was working fine until v13.3, at which point some changes introduced in the Next server led to interference with my middleware, see https://github.com/vercel/next.js/issues/50464 Now I could work around the middleware, but my hack to revalidate in dev mode definitely does not work anymore starting in v13.5 or so. This all sounds convoluted, and it is, but my feeling is that the issues (with the old method) would be fairly easy to resolve if somebody cared to look. Alternatively, I'd be happy to wait if there was a clear statement about what the plans are to finally address the issues that @markomitranic you so well summarized.
Operating System: Platform: darwin Arch: x64 Version: Darwin Kernel Version 21.6.0: Thu Sep 29 20:12:57 PDT 2022; root:xnu-8020.240.7~1/RELEASE_X86_64 Binaries: Node: 18.13.0 npm: 8.19.3 Yarn: 1.22.10 pnpm: 8.3.1 Relevant packages: next: 13.3.0 eslint-config-next: 13.3.0 react: 18.2.0 react-dom: 18.2.0
My Next.js project is not functioning properly in the production environment (Firebase Hosting). When I run the build
, export
, and start
commands locally on my machine, everything works fine. However, I'm encountering issues with the revalidate and fallback features not working as expected in the production environment.
I have already updated my Next.js version to 13.3.0 based on this discussion https://github.com/vercel/next.js/discussions/42290#discussioncomment-5502200, but the issue persists.
I expect the revalidate and fallback features to work correctly in the production environment as they do on my local machine.
Actual Behavior: In the production environment, the revalidate and fallback features are not functioning as expected. The pages do not update automatically with the specified revalidate interval, and the fallback behavior is not working with new params that wasn't specified initially.
My page is /profile/[id].tsx
const Profile: NextPage<ProfileProps> = ({ profile }) => {
const { isFallback } = useRouter()
if (isFallback) {
return <Loading />
}
return (
...
)
}
export const getStaticPaths: GetStaticPaths = async () => {
const urlIds = ['1']
const paths = urlIds.map((urlId) => ({
params: { id: urlId }
}))
return { paths, fallback: true }
}
export const getStaticProps: GetStaticProps<ProfileProps> = async ({ params }) => {
const urlId = params?.id
const response = await api.get(`profiles/${urlId}`)
const profile: Profile | null = response.data?.profile || null
return { props: { profile }, revalidate: 30 }
}
export default Profile
The lack of documentation of these issue is a bit surprising.
@jwalcher to be clear, you are referring to an unstable API that will change and should not yet be adopted. Unstable features are not published to the documentation for this reason.
@edjust please open a separate issue with a reproduction 🙏
It is kind of weird that Next, a framework known for championing caching stuff into the mainstream, released a version that just glosses over the whole caching thing, in a release that was supposed to be all about caching
I don't know if I'd say we "glossed over it" – it's documented! But we are working to make the documentation better and add diagrams to help explains concepts. That should be landing shortly https://github.com/vercel/next.js/pull/52514.
@leerob oh, I wasn't aware that it was unstable, that changes things a lot and I'm sorry for saying "glossed over". I was under the impression that both Route Handlers and revalidate
are stable. Probably as there is no warning on their docs saying they are unstable :/
In any case, I don't think there is a misunderstanding of diagrams here, its purely that a major piece of old functionality is missing entirely.
@leerob to follow up on @markomitranic -- the issue for me is that the development of the (as you say) unstable revalidatePath/revalidateTag
API has broken the old res.revalidate()
(at least for me). So I'm a bit stuck between a rock and a hard place here. Otherwise happy to wait!
Verify canary release
Provide environment information
Which area(s) of Next.js are affected? (leave empty if unsure)
App directory (appDir: true)
Link to the code that reproduces this issue
https://github.com/roxizhauk/revalidate-path CodeSandBox
To Reproduce
Visit
/blog/[anything]
(e.g./blog/test
) to generate a dynamic page and check the time shownTo try "unsuccessful" app directory's
revalidatePath
:/api/revalidate-path?path=/blog/[anything]
and you'll see "revalidated"/blog/[anything]
and you'll see the time not changedTo try "successful" pages directory's
res.revalidate
:/api/revalidate?path=/blog/[anything]
and you'll see "revalidated"/blog/[anything]
and you'll see the time changedDescribe the Bug
The app directory's
revalidatePath
works fine for "/" or "/blog" but dynamic routes like "/blog/1" or "/blog/test" while pages directory'sres.revalidate
works fine for allExpected Behavior
revalidatePath
works the same asres.revalidate
for dynamic routesWhich browser are you using? (if relevant)
No response
How are you deploying your application? (if relevant)
No response
From SyncLinear.com | NEXT-1186