Gridsome: <g-link> doesn't actually change pages on build - Hydration issue

Created on 9 Sep 2019  路  33Comments  路  Source: gridsome/gridsome

Description

updates the page title (in the browser tabs) and loads things like the console log but it does not change what I see on the page without reloading. In gridsome develop this is not an issue but gridsome build it fails.

I'm assuming I might have invalid HTML somewhere, but perhaps it could be something else, any suggestions?

I've looked at a lot of other similar g-link issues like https://github.com/gridsome/gridsome/issues/337 but to no prevail.

Steps to reproduce

https://github.com/element-softworks/atobtyres

Expected result

<g-link> should hydrate the pages without having to reload the page manually

Actual result

The page does visually not change unless I reload the page, I do think the code is loaded, just the view doesn't seem to change.

Environment


Libs:
- gridsome version: 0.6.6
- @gridsome/cli version: 0.2.0


Browser:
- [x] Chrome (desktop) version
- [x] Chrome (iOS) version
- [x] Safari (desktop) version

For Tooling issues:
- Node version: 10.13  
- Platform: Mac

Most helpful comment

Two options I think could be acceptable would be that it breaks during development in the same way it breaks during production build. Or it at least gives a console warning if there's invalid HTML. I mean, ideally a developer knows how to avoid invalid HTML, but machines are way better than humans at that.

All 33 comments

I've seen some other people have also reported this issue, is this a known issue or more likely is it due to invalid HTML somewhere?

I would say it's the latter, @LukeXF - since there are no console errors, it's hard to pin it down. In my case it was an <a> anchor wrapping a component (a simple one too) in Default.vue. The exact line change is here, in case it helps you to reproduce.

Thanks for getting back to me, I check my code and still can't seem to find the issue. Is anyone else able to provide suggestions?

I have same issue.... After clicking on link page not loader.... Loaded perfect when I refresh page

I just came across this issue too and realised it was something I was doing that was causing an error with the html markup as well. I'd accidentally nested an anchor tag within another anchor tag. It was hard to spot though as they were both using <component> tags with dynamic is props.

I came across this recently. I was nesting a g-link within a g-link. Removing that nesting fixed this for me. It'd be great if some warning could be displayed to let people know about this issue in their components.

I too am hitting a frustrating issue where routing and/or hydration is failing (silently) on build but not on development. Clicking on G-link links updates the URL, the meta info (the title in the browser tab changes, too), however the view is not updated.

Slowly through a process of trial and error and rebuilding the production site each time I'm working on narrowing it down to some sort of issue with one of my components, but it would be very helpful to have some sort of error in the console to indicate why this might be happening. Adding config.mode('development') to chainWebpack inside grime.config.js hasn't changed anything in terms of helpful messages or notices.

I wanted to give everyone an update to this issue.

We managed to fix the issue on the 24th December:

  • The issue was with our Services.vue file
  • We had to switch mounted() to computed() to set title and text
  • Perhaps updating this.text and this.title onmounted() broken it

Not really sure how we fixed it but the below commit fixed the hydration issue.
https://github.com/element-softworks/atobtyres/compare/6afde94cbe00...b8cf43151638

I will leave this open for the Gridsome team to explain what I was doing wrong, or confirm whether or not an actual bug exists.

Side note: We have since started building in Gatsby (React) because we kept running into obscure issues with Gridsome (like this issue).

@timchambers we also solved our issue by trial and error of rebuilding the site in production each time. It was very time consuming and caused massive frustration for all of our developers because there was no help/error to where the actual issue was.

I think the Gridsome team should have a check on if there are hydration issues, and perhaps provide more detailed information to what could be causing it. Gridsome: I understand that hydration issues may be hard to find/show errors for, but my team and I spent over 6 hours trying to debug this issue by slowly rebuilding the whole site.

Anyway, I hope that helps, Tim.

I am also facing this issue right now. Links works very well in all browsers on Windows, but fail to change in some browsers on Mac and iOS.

I had some headline tags (<h1>) which contained <div>s. I had to remove them to be HTML compliant and make it work on my iPad. But it keeps failing in Safari on Mac.

Like @LukeXF said, it is really hard to identify the cause of the problem(s?). Do you have any hint like verbose logs or something that could help us on this?

Two options I think could be acceptable would be that it breaks during development in the same way it breaks during production build. Or it at least gives a console warning if there's invalid HTML. I mean, ideally a developer knows how to avoid invalid HTML, but machines are way better than humans at that.

Two options I think could be acceptable would be that it breaks during development in the same way it breaks during production build. Or it at least gives a console warning if there's invalid HTML. I mean, ideally a developer knows how to avoid invalid HTML, but machines are way better than humans at that.

Yes, I definitely agree. Developers need to be made aware of hydration issues in development (and not go hunting for them in production)

I think I got bitten by this too. In my setup, using source-filesystem to read markdown files, the Article.vue template contained <p v-html="$page.article.content"></p>, where $page.article.content is the markdown transformed to HTML. This was a mistake, because markdown produces <p> elements and nested paragraphs are not allowed.

Debugging this was especially hard because the resulting build completely crashed the browser tab in both Firefox and Chromium (Linux, versions 74 and 80 respectively). The tab did render the static HTML content, but froze while hydrating, not even reacting to a right-click or Ctrl-Shift-I to open the inspector. At least Firefox showed a console error after the tab process was killed:

Error: Script terminated by timeout at:
ln.prototype.depend@https://example.com/assets/js/app.7f071284.js:7:27880

At line 7, around the 27880th character, it read:

ln.prototype.depend=function(){for(var t=this.deps.length;t--;)this.deps[t].depend()}
                                                          ^
                                                          char 27880

I tried reproducing this browser tab crash in a minimal VueJS project, but that didn't succeed.

Anyway, once I changed my code to <div v-html="$page.article.content"></div> everything was fine again.

I was dealing with the same issue 3 days ago till today. After reading the comments i decided to forget my assumptions, relax and debug my website. And I ended descovering that the issue was being caused by netlify's form attribute that I added on other day. I removed it and my site is now working.

Know I have to found out how to properly integrate my website with netlify.
I hope this saves someone hours.

Hello, today I uploaded my site to production and to my surprise the pages did not change. It is quite sad because I already have many pages made, to find all the problems it will be a martyrdom. I followed all the recommendations that are here, it helped me but it did not solve the whole problem. At this very moment I have identified the problem, but I do not understand why this is happening to me. It turns out that putting v-html = "sections [0] .node.about" causes the problem. But if I put a fixed value the problem disappears.

In my case there are no incorrectly nested elements, but:

  1. The server creates the page, and there is a list on it
  2. On the live server, based on an expiration date one or more extra elements can be added to this list

I've been debugging this issue for hours now, because the previously exported page had the issue, but the new exports didn't, and I simply couldn't understand what the difference was between the two.
So, just as everybody else, I too started removing elements, and hacking around in the minified JS code, until I narrowed it down to the list.
Then I looked for incorrect nesting, but there was nothing. As a last try I went ahead, and replaced the list in the old export, with the one from the new. And bumm, it worked. Checked the diff between the two pages, and that's when I realized that the only difference is that the new page had the expired list item in the list, while the old one didn't.
Of course, the data is exactly the same between the two versions.

Just to make sure it is easier to imagine.

This is the simplified view of the old page:

<ul>
  <li>item 1</li>
  <li>item 2</li>
</ul>

The data that belongs to this:

const data = [
  { id: 1, title: 'item 1', expire: '2020-01-01' },
  { id: 2, title: 'item 2', expire: '2020-01-02' },
  { id: 3, title: 'item 3', expire: 'some future date' }
]

After the some future date the navigation on the page stops working. If I re-build the page, the only difference is going to be that the HTML is like this:

<ul>
  <li>item 1</li>
  <li>item 2</li>
  <li>item 3</li>
</ul>

And if I add the <li>item 3</li> manually to the old version, the navigation starts working again.
By the way, the list is generated by a v-for loop, and has a :key set.

This is quite a serious issue, I believe.

Note, I made some sample repro code with my previous example:
https://github.com/csabaxyz/gridsome-issue-650

The readme explains how to build it. The date is determined at build time, and after 2 minutes the third list item becomes active. Try to load the index page that you built, refresh the page in two minutes when the Item 3 becomes visible, and click on the About link. The about page won't load.

The generated list in the index.html looks like this:

<ul data-v-8ed51186><li data-v-8ed51186>Item 1</li><li data-v-8ed51186>Item 2</li></ul>

If you add the third item to this, refresh the generated page, and click on the link, the about page will correctly load.

<ul data-v-8ed51186><li data-v-8ed51186>Item 1</li><li data-v-8ed51186>Item 2</li><li data-v-8ed51186>Item 3</li></ul>

In dev mode this works without an issue, so make sure to test the built files.

Thanks for the repo, @csabaxyz. I'm beginning to suspect that the unresponsive g-links are not the problem, but merely the symptom of a variety of errors which make the hydration crash. Maybe the most important thing to fix here is the debuggability (is that a word?) of the hydration.

@marcvangend That would definitely be a step forward. However there aren't any real issues with the code that I have, so it basically cannot be debugged.

But, even if the problem can't be solved easily, I'd be glad if the page would at least do a hard refresh automatically if it can't load the next page because of hydration issues. That's what users have to do anyway, so that would at least make the page seem working.

I just got the same issue.

I had an issue only when starting on specific pages (like most people here I guess).
Those pages reported no significant issue on the w3c validator.
Even stranger: my staging environment was working fine, but the production was failing.

It turned out that the problem was with Cloudflare email protection:
the faulting (starting) pages contained an e-mail address which was obfuscated by cloudflare (and automatically de-obfuscated client side).
I also had a page with an email address, which worked perfectly fine (despite the obfuscation).

It turns out that the buggy page didn't have a <a href="mailto:..." link!

So if you have the same issue, only on Cloudflare, check if the faulty page has an email without a mailto link.
To fix it, simply surround it with a link: <a href="mailto:[email protected]">[email protected]</a>


I do agree with @marcvangend that the debuggability could be greatly improved!
(I spent one hour debugging my production website in the dark, since there is no log regarding the hydration crash)

Hello!! I've had the same issue. I've read the whole thread and in my case, the issue was that I had a <g-link> inside another <g-link>

Here an example (_PostList.vue component_):

Initial code:

**<g-link :to="post.path">**
     <div class="card-style rounded overflow-hidden shadow-lg">
        <g-image v-if="post.img" class="w-full" :src="post.img" alt="Sunset in the mountains" />
        <div class="px-6 py-4">
          <div class="font-bold text-xl text-center" v-html="post.title"></div>
          <div class="text-center text-xs text-gray-600">
            <span v-html="post.date" />
            <b> {{post.timeToRead}} min lectura </b>
          </div>      
          <p class="text-gray-800 text-base pt-3 pb-3" v-html="post.description" />
          <p :to="post.path">Leer m谩s...</p>
        </div>
      <div class="px-6 py-4">
        **<g-link** class="inline-block bg-gray-200 rounded-full px-3 py-1 text-xs font-semibold text-gray-700 mr-2" v-for="tag in post.tags" :key="tag.id" :to="tag.path">
          <span>#</span> {{ tag.title }}
        **</g-link>**
      </div>
    </div>
**</g-link>**

Solution:

<div class="card-style rounded overflow-hidden shadow-lg">
      **<g-link :to="post.path">**
        <g-image v-if="post.img" class="w-full" :src="post.img" alt="Sunset in the mountains" />
        <div class="px-6 py-4">
          <div class="font-bold text-xl text-center" v-html="post.title"></div>
          <div class="text-center text-xs text-gray-600">
            <span v-html="post.date" />
            <b> {{post.timeToRead}} min lectura </b>
          </div>      
          <p class="text-gray-800 text-base pt-3 pb-3" v-html="post.description" />
          <p :to="post.path">Leer m谩s...</p>
        </div>
      **</g-link>**
      <div class="px-6 py-4">
        **<g-link** class="inline-block bg-gray-200 rounded-full px-3 py-1 text-xs font-semibold text-gray-700 mr-2" v-for="tag in post.tags" :key="tag.id" :to="tag.path">
          <span>#</span> {{ tag.title }}
        **</g-link>**
      </div>
    </div>

_NOTE: I've added the ** symbol into the code to find the <g-link> tags easier._

Having a similar problem with hydration. On dev it works fine but when build g-links stop working.
Because i also have a Netlify form in place at first i thought that was the issue.

After some extensive testing, which was super annoying having to run several builds and not getting any warning or feedback, i managed to narrow down the issue for my case.

I'm using vuelidate and that seems to be the one causing the problems.
<p class="error" v-if="$v.formData.$dirty &&$v.formData.naam.$invalid" > {{ usernameErrorMessage }} </p>

Anyone got same experience and knows a fix? Tried ClientOnly, v-show instead of v-if but to no avail.

@Wvduijn are you sure your code produces valid HTML? I can't tell because I don't know the output of {{ usernameErrorMessage }}, but if it contains HTML that is not allowed inside a <p> element, that could be the problem. Did you try changing the <p> to a <div>, and/or using v-html like this?

<div class="error" v-if="$v.formData.$dirty && $v.formData.naam.$invalid" v-html="usernameErrorMessage"></div>

Bumped into this issue, definitely took a while to track down what it was. It's awfully weird that it breaks routing.

Seems like it isn't a Gridsome problem though, I suspect we need Vue to warn us when it has to force hydration in development mode.

I ran into this issue on a single page of my website. When starting from the any page other than the affected page, clicking around to any page (including the affected page, and from the affected page) worked fine. But when starting from the affected page (including navigating to there and then reloading the page) then attempting to navigate to any other page caused the window to scroll to the top and the title and address bar to be updated to the destination, but not the content.

The thing that caused the error was a <!-- comment --> inside a p tag on the affected page. That's valid HTML but for some reason was causing the issue. I validated the entire page with the W3C validator, there were 4 unrelated issues that also were found on my other pages. Removing the comment, or moving it to be above the enclosing div, fixed it for me.

I also debugged this problem in my application.
In my case, it wasn't a specific problem with g-link, but with my attempt to filter my data.

  • i use createPage() to add detailpages for my collection 'news'
  • i used async mounted to populate my data with some extra logic
  • after building, i tried to switch pages with internal and relative links (doesn't matter if <g-link>, <router-link> or just <a> )
  • url changed, but not my content, but I noticed a new index.json were loaded over the network
  • breaking it down showed that async mounted wasn't executed after clicking the internal link

I removed

async mounted() {
    this.headline = this.filter_headline();
    ...
}

and created a computed value

filteredHeadline: function() {
    const headline = this.$page.topics.page.headline;
    const seasonHeadline = this.seasonalized(headline);
}

I guess Vue reuses the same template component instance and doesn't execute async mounted while switching between pages of the same collection type.
As mentioned before, reloading the page forced it to load everything from scratch and i got my expected result.

In my case, I had a <ul> in a <p>. Very strange and unexpected.

General advice (helped me): Go to https://validator.w3.org/#validate_by_input and paste your generated html code into the textfield for validation. Click Check. Fix html errors.

For me, the problem was a <g-link> as the root element of a Vue component. Putting a div around it fixed it for me.

@allanShady this error also occured to my prod website after netlify form integration. Dit you find a solution? Because this seems to be the only way to get a form up and running, quite frustrating. Also is Gridsome still active? This issue is a long-living one.

@nielsvhb what is the css framework are you using?

  1. Anyway you have to validate your html here ;
  2. If You are using Tailwind CSS or another CSS framework, you may need to purge it on production;
  3. Or you can share your project repository to see if someone can yelp you here.

I think gridsome team still managing it and seem they had a lot issues and many cases pointed here are, often, related to the third part solutions.

@allanShady Validation is okay, and I'm using Tailwindcss which I purge. Issue seemed to come accross when I integrated Netlify form. I thought you had the same issue, that's why I wondered how you solved it.

@nielsvhb are You using data-netlify="true" attribute on your

tag? If so, try to remove it and see what is the result.

        -    <form action="#" class="mb-12" method="POST" data-netlify="true">
        +   <form action="#" class="mb-12" method="POST" >
Was this page helpful?
0 / 5 - 0 ratings

Related issues

gongph picture gongph  路  42Comments

Jonarod picture Jonarod  路  21Comments

itech001 picture itech001  路  32Comments

eleijonmarck picture eleijonmarck  路  18Comments

tanc picture tanc  路  26Comments