Open jhull opened 3 years ago
Hi @jhull, if I understand correctly, is your aim just to get the latest articles, analyses & blog posts like in a home page of some sort?
Another question is may I know what does the $fetchState.pending
block shows? If this is intended as a full static site, the usage seems unusual here. Though it can definitely be a valid use case depending on what you want to achieve or show to the users, hence I would like to understand clearer.
EDIT: Just a quick follow up question, is there a reason for not using asyncData() method here?
I could be using it wrong...didn't really consider the thinking behind it. And yes, it's a "home page" of sorts in much the same way you describe. I figured this was a typical use case...
fetchState
is a simple spinner that lets users know its loading the latest content.
Right now, I create a new piece of content and rebuild the whole site. But I can see a future where I just upload that one file change and not have to rebuild the entire site.
And I've never really understood difference between asyncData
and fetch
. They seem the same, with the latter being the more modern up-to-date approach.
No worries. There's nothing wrong with using fetch() to get the data on client side when they visit the page, and this is definitely a valid use case depending on situations. However, I do believe you will benefit more with using asyncData() without having to wait for the fetch() in this particular scenario :)
And I've never really understood difference between asyncData and fetch. They seem the same, with the latter being the more modern up-to-date approach.
Rest assured I was not sure of their difference in the beginning as well haha. I might be oversimplifying here, but I think we can think asyncData()
as being done before the page is served to the user. Which means what ever is done in there, won't be done on the client side at all. Though this is true for SSR, it behave slightly different when you are using full static. When you run nuxt generate
command, Nuxt have a crawler that will go through each pages/links and run the asyncData() once and generate the final HTML files.
As for fetch()
, the default behaviour is running it once on the server unless you disable it using fetchOnServer: false
(reference) in SSR. However in your case, you are using full static, so it means it will only ever run on client side. This means whenever someone visits the homepage, they will fetch from the built API that is served by your generated files, do 3 await calls then run sort over each item in the array which can be pretty taxing in terms of processing.
Do note that I mentioned *built API files, which means they are static and are baked in to your dist
folder, and the fetch() are technically fetching from the built static files, not directly from your GitHub repo. So when you mentioned you want to upload one file change and not have to rebuild the entire site, it will not be possible with this approach. With that said, many static site hosting services like Netlify does provide github repo integration, so you don't have to worry about manually rebuilding the site. You just need to push a commit and the rebuild is done automatically for you.
Sorry if the explanation is too much. Just try out the proposed solution below and see how it is for you.
I am going to translate your existing code to asyncData() here, so I'll try to mimic your code since I can't truly see the whole source code. Hope it's roughly accurate here.
<template>
<template v-if="$fetchState.pending">
<!-- Show the spinner here -->
</template>
<template v-else>
<!-- Loop through **latestContent** computed array here to show the articles -->
</template>
</template>
<script>
export default {
data() {
return {
latestArticles: [],
latestAnalyses: [],
latestBlog: [],
}
},
async fetch() {
// the 3 await $content calls here
},
computed: {
latestContent() {
// your sorting code here
}
}
}
<template>
<div>
<!-- Loop through **latestPosts** data array here to show the articles -->
</div>
</template>
<script>
export default {
async asyncData({ $content }) {
const results = await Promise.all([
$content('articles').sortBy('published', 'desc').limit(5).fetch(),
$content('analysis').sortBy('published', 'desc').limit(5).fetch(),
$content('blog').sortBy('published', 'desc').limit(10).fetch()
])
const unsortedPosts = [].concat(...results)
const sortedPosts = unsortedPosts.sort((a, b) => {
const keyA = new Date(a.published), keyB = new Date(b.published);
// Compare the 2 dates
if (keyA < keyB) return 1;
if (keyA > keyB) return -1;
return 0;
})
return { latestPosts: sortedPosts }
},
}
The latestPosts
returned in asyncData will be added to the data() option, that's why we don't even need to specify data()
like in fetch example anymore. And since you are doing the sorting during build process, your client side never needs to run any fetching or sorting and should be able to instantly see the posts in your homepage.
Further explanation:
Would you mind giving this solution a try? Feel free to change the variable names I used to what you see fit.
I really really appreciate the in-depth description!
I followed it exactly and it worked great locally, but in production (Netlify SSR) it's empty...
Glad it's helpful. Btw I think we shouldn't categorize Netlify as doing SSR since it's not a compute like Heroku running Nodejs for server side rendering. It can only serve/host full static sites or a SPA.
Since it worked locally, we'll need more info to work with here.
nuxt.config.js
configuration for "target"? The whole config file would be appreciated and you can obscure any sensitive data in it before pasting here.yarn dev
(or npm run dev
)? if so, can you try yarn generate
then yarn start
to test the built static files?/dist
folder, especially the homepage html file (should be index.html unless these articles are on another page), can you verify the HTML file contains the articles in HTML tags?These are just the debugging steps I can think of. Since it worked locally but not in Netlify, we should try to narrow down is it the /dist
folder (or generated static files) being incorrect, or you're passing something else to Netlify here. Another possibility is I suspect you are doing target: server
so it will work locally (since your machine is running nodejs for it to do SSR) and you passed the files to Netlify that can't do SSR. Another possibility is you are running build
instead of generate
. Do kindly provide more info so it's easier for us to work out the issue :)
Thank you so much for the detailed response. So very much appreciated. 😃
I'm using target: 'static'
, and the Netlify config is as suggested with the exception of using yarn generate
instead of npm run generate
.
When it runs locally, yes that's when I use yarn dev
. When I do yarn generate
and then yarn start
, that "home page" is indeed blank. Looking at the generated file, it's a ton of minified CSS with some script at the end - no content. So there is something weird with the build process (though it is building it).
The only thing "odd" I can think of is that I'm using a handful of Promise-based functions - these work as expected...
Here is the pertinent info from nuxt.config.js
:
export default {
mode: 'universal',
target: 'static',
generate: {
routes: buildRoutes,
fallback: true,
exclude: [
/^\/settings/,
]
},
}
If that "home page" has a middleware: auth
on it, could that be causing it to not render?
If that "home page" has a middleware: auth on it, could that be causing it to not render?
Hmm I'm not particular sure about this, but just to be clear, does the auth means no public access at all? And when you tested locally, are you authenticated? If yes, does it work if you're not authenticated?
This might be difficult if you have to redact a lot of sensitive data, but would you be able to provide a codesandbox reproduction environment?
Hello 🙂
Has your issue been fixed?
I think this is still relevant for v2, so I'm keeping this open, would love to see performances benchmarks between v1 and v2!
This may be a result of having too much content (1200 pages), but on the initial load of "The Latest" content - it can sometimes take several minutes, and a couple refreshes to actually see the newest content using
content
. Locally it happens in a matter of seconds, but in production (SSR full static) - it takes too long...My current implementation:
and then in a computed property, I mash them together like so:
I'm pretty sure it's not the
latestContent
, because my$fetchState.pending
block runs throughout that entire time.Again, this is for
target: static
, so I would assume even during the build process there should be something there at first, yes?