Nuxt Async Data - Server is Caching - vue.js

Im using nuxt with asyncData() to make an axios request to an endpoint. In my build i'm using pre-rendered HTML pages.
I have a set of products on the API end-point and we've just remove most of the products, however they are still showing the full product list.
So I started up my dev server and hit the endpoint and I am seeing the correct updated API list from the endpoint.
So it seems my server is caching the API call. I'm not using a node server, just uploading my pre-rendered html to a server.
It's just I'm trying to isolate the problem and wanted to know if it is a configuration with nuxt.js that will allow me to not cache from the endpoint or is this a strictly a server issue that is causing the API data to be cached?
Or is there a config that I can use in the AXIOS request to always give me a fresh copy?

are you running nuxt with static site generation? in this case nuxt fetches all products from your API at the time it generates the static html. so the nuxt-server does not know anything about the updated api-data.
you could solve this by using a hook and re-building the page every time the api-data changes.
edit: you can find more info in the docs

Related

How do dynamic API calls work in Nuxt.js static vs SSR mode?

Even after reading through multiple articles explaining the differences between static and SSR rendering I still don't understand how dynamic API calls work in these different modes.
I know that Nuxt has the fetch and asyncData hooks which are only called once during static generation, but what if I use dynamic HTTP requests inside component methods (e.g. when submitting a form via a POST request)? Does that even work in static sites?
I'm making a site that shows user generated content on most pages, so I have to make GET requests everytime one of those pages is visited to keep the content up to date. Can I do that with a static site or do I have to use SSR / something else? I don't want to use client side rendering (SPA mode) because it's slow and bad for SEO. So what is my best option?
There is actually no difference between either asyncData() or fetch() hooks when you do use target: static (SSG) or target: server (default, SSR).
At least, not in your use-case.
They are used mainly by your hydrated app.
As a reminder, when using either SSG or SSR, your static page will be hydrated and will become an SPA with all the dynamic functionality that we love. This combo of SSG + SPA or SSR + SPA is called an universal app (or isomorphic app).
Both asyncData() and fetch() will be called upon navigation within your client side SPA.
There are also some things happening on the server side, like fetch being called (by default) when you request the server for an SSR built app.
Or the fact that when you generate your app (if using SSG), you can reach some API and generate dynamic routes (useful in the case of a headless CMS + blog combo for example).
For performance reasons and to have a quick build time, you may pass a payload and use it in an asyncData hook in the dynamic route, as explained here
Still, a static Nuxt app, is basically just an app built ahead of time, with no need for a Node.js server, hence why an SSG app can be hosted on Netlify for free (CDN) but and SSR one needs to be hosted on something like Heroku (on a paid VPS).
The main questions to ask yourself here are:
do you need to have some content protected? Like some video courses, private user info etc...already in your Nuxt project (if SSG, disabling the JS will give access to the generated content)
is your first page a login? Is it mandatory to access the rest of the content? Like an admin dashboard (you cannot generate content ahead of time if the data is private, think of Facebook's feed being generated for every account, not feasible and not secure as above)
is my API updating super often and do I need to have some super quick build time (limitation on free tiers essentially)? (SSG will need a re-generation each time the API changes)
If none of those are relevant, you can totally go SSG.
If one of those is important to you, you may consider SSR.
I do recommend trying all of them:
SSR (ssr: true + target: server) with yarn build && yarn start
SSG (ssr: true + target: static) with yarn generate && yarn start
SPA only (ssr: false + either target: static, target: server also work but who wants to pay for an SPA?!) with yarn generate && yarn start
Try to host it on some platforms too, if you want to be sure to understand the differences beyond your local build.
You can use this kind of extension to also double-check the behavior of having JS enabled or not.
I will probably recommend to take the SSG path. Even tho, if your content is always changing you will probably not benefit much from SEO (eg: Twitter or Facebook).
This github answer could maybe help you understand things a bit better (it does have some videos from Atinux).
PS: I did a video about this on the latest Nuxtnation that you can find here.
I use dynamic HTTP requests inside component methods (e.g. when submitting a form via a POST request)? Does that even work in static sites?
The short answer to this question is that yes, it does work. In fact you can have http requests in any life cycle hooks or methods in your code, and they all work fine with static mode too.
Static site generation and ssr mode in Nuxt.js are tools to help you with SEO issues and I will explain the difference with an example.
Imagine you have a blog post page at a url like coolsite.com/blogs with some posts that are coming from a database.
SPA
In this mode, when a user visits the said URL server basically responds with a .js file, then in the client this .js file will be rendered. A Vue instance gets created and when the app reaches the code for the get posts request for example in the created hook, it makes an API call, gets the result and renders the posts to the DOM.
This is not cool for SEO since at the first app load there isn't any content and all search engine web crawlers are better at understanding content as html rather than js.
SSR
In this mode if you use the asyncData hook, when the user requests for the said URL, the server runs the code in the asyncData hook in which you should have your API call for the blog posts. It gets the result, renders it as an html page and sends that back to the user with the content already inside it (the Vue instance still gets created in the client). There is no need for any further request from client to server. Of course you still can have api calls in other methods or hooks.
The drawback here is that you need a certain way for deployment for this to work since the code must run on the server. For example you need node.js web hosting to run your app on the server.
STATIC
This mode is actually a compromise between the last two. It means you can have static web hosting but still make your app better for SEO.
The way it works is simple. You use asyncData again but here, when you are generating your app in your local machine it runs the code inside asyncData, gets the posts, and then renders the proper html for each of your app routes. So when you deploy and the user requests that URL, she/he will get a rendered page just like the one in SSR mode.
But the drawback here is that if you add a post to your database, you need to generate your app in your local machine, and update the required file(s) on your server with newly generated files in order for the user to get the latest content.
Apart from this, any other API call will work just fine since the code required for this is already shipped to the client.
Side note: I used asyncData in my example since this is the hook you should use in page level but fetch is also a Nuxt.js hook that works more or less the same for the component level.

In a Nuxt SSR application, what happens on server and what on client?

I'm on Nuxt 2.13 and building an e-commerce website.
But the are some issues with my server resources, my first load of site takes some time (on route change every thing is ok and fast, just the init is slow).
So i wanna know which parts of my site will be on server and which parts on client browser.
for example as recommended, i use fetch() with axios to get page/component data. as i read the docs it is said on render route it is server-side and on navigation it is client side. so what does that mean? my axios call in fetch() in on server or client? what about my other axios calls in methods to backend?
what i wanna understand is that which parts are on server? and can i make them client-side to save server resources? (I'm afraid with some users the resource usage get too high!!)
That's point of fetch. It's called when it's needed. On server side during initial page load, than all page state is send along with rendered page to client. All following navigation is calling fetch on client side only.
On basic level, you can't care about it.
In reality, to speed up initial load, you may decide to load something always on client. Then you can move it to mounter() hook which is always called only on client side.

NuxtJs generate for dynamic websites?

I'm creating a simple demo app with NuxtJs. The homepage shows static content that is not changed very often. There is another route for showing a list of users: /users. And one for showing user's details: /user/id.
Now my question is what's the difference between nuxt generate and nuxt build? which one should I use?
I think nuxt generate page will not render dynamic routes like users and user/id, Am I right? If I am right, then generate command will generate a pre-rendered HTML for homepage only. So using generate is always better than using build right ?
In universal mode, nuxt generate is for static site generation. nuxt build is for SSR site.
In 2.13.0, Nuxt introduced a target: static feature, make sure to
check it.
A static site has the best performance, and it is easy to deploy on nginx or other services, like Netlify.
By default, nuxt generate only render your static home page and /users page, not the dynamic /user/:id route.
But you can config nuxt to help you generate the dynamic routes.
If you have a fixed set of users, you can use functions to generate the routes.
If the users data is constantly in change, you can config nuxt to fallback to SPA on the dynamic routes. But you can't get any benefit for SEO on the dynamic routes.
For SPA fallback, in the generate config, define a custom page for SPA fallback:
export default {
generate: {
fallback: "custom_sap_fallbackpage.html"
}
}
Config the fallback page for unknow route in your deployment, for example, in Nginx:
location / {
try_files $uri /custom_sap_fallbackpage.html;
}
nuxt build will build you a SSR site. The html is rendered on the server and sent to the client. It add some work load on the server and maybe is not that easy to deploy, but the main gain is the SEO. And to some users with low end devices or slow internet connection, maybe your site will perform better than depolying in SPA mode.
Basically, you need to consider:
The website's content is static or constantly changing?
nuxt generate for static. nuxt generate or nuxt build or spa mode for sites with dynamic routes.
Do you need SEO?
SPA wouldn't get any SEO.
How you deploy the site?
For static hosting service, only nuxt generate or spa mode will work.
your website is heavy with js code, and you want best performance for user with slow internet and slow devices. Or SEO is important for your site with a lot of dynamic content.
SSR is for you, use nuxt build.
There are three different deployment and generation options in Nuxt.
Universal Mode
In this mode you build your project and then you ship it to a node.js server, the first view is always rendered dynamically on the server and then turns into SPA, and works in the client. That's great for SEO, and for consuming API's but you cannot upload it to any hosting, for example on a shared VPS.
So - Node.js Host is required here.
SPA
Well basically how Vue.js works by default, virtually no SEO at all, you can upload it on a shared VPS hosting, because it's just an index.html and build.js file and it's working entirely on the client-side (in the browser).
We can go for a static hosting here.
Static App
This is where Nuxt.js shines, because this mode will generate an index.html file and the corresponding js/css assets for each route you have in the dist folder, and you can then just take those numerous files, and upload them to any hosting, you don't need a server here, because your first views are already pre-rendered, unlike Universal where the node server should pre-render the first view. So you get SSR here, and your main concert as far as I understand is if you get SPA too, and that's the best part as in Universal mode, after the first request the app continues in SPA mode, how great is that eh?
Anyways there are some things you should take into consideration, that if you want to generate index.html for dynamic content you need to make something that's kinda a mood killer. You need to add this to nuxt-config.js
generate: {
routes: () => {
return [
'/posts/1'
]
}
}
You can also use axios to make http request and return array here. Or even export default array from a file and include it here, where you combine all your dynamic routes. It's a one time job, but if you add new crud in your backend, that would add up 1 more request to run on executing nuxt generate that should be described in nuxt-config.
So that's the reason I would prefer to pay more for a server, but to host a Universal App, instead static generated, because that's the part that doesn't make it really great for consuming API's in my personal opinion, but it is a great future anyways.
when you website update data often you don't need to use build by using npm generate your website static, load fast and SEO friendly for search engine and more secure and if your project has data NuxtJS download all data from database and change data to .json file statically.
if your website load data from the database you must use npm build to load data dynamically from database. use mode "spa" for a single page without client-side rendering or "universal" in nuxt.config.js for client-side rendering.
for dynamic routing use npm build for change route parameters from the database.

Use axios instead of fetch requests in Workbox

Im trying to use workbox to save in cache some stuff for my project, I have already made it to save all my js and css files, fonts, etc, there's one thing missing and that is my project's content that is stored in my pc, Im using axios to fetch my database data, workbox seems to ignore the requests sent from axios, I have made a test and changed one axios request to "fetch" and it worked, it was successfully cached, theres any way to make it work using axios?
This is my code:
importScripts("https://storage.googleapis.com/workbox-cdn/releases/4.3.0/workbox-sw.js");
workbox.routing.registerRoute(
new RegExp('http://localhost/Odr/connections/'),
workbox.strategies.cacheFirst(),
);
There's nothing specific about axios that should prevent its requests from being intercepted by Workbox, or in general, from triggering the fetch handler inside of a service worker. XMLHttpRequests made from client pages do result in the fetch handler being fired.
I would recommend using a debug build of Workbox (which is the default if you're developing on http://localhost) and then opening the JavaScript console when you attempt your axios request. There are debugging messages that should shed light on Workbox's routing logic, including whether a particular request triggering a route or not.

Dynamically change API route for SPA

I am currently building a SPA app using Vue.js and webpack to do our bundling. The backend API is built with .Net Core. When running locally, the Vue app is hitting localhost on the backend. I need to be able to change the route of the API dynamically based on the environment. Is there a way to do this without having to do a big switch statement that considers the current url? A requirement is that we are not allowed to change the webpack bundle for different environments, in other words, once it is bundled, it has to stay bundled. I have tried to pass static config files through to the bundle and dynamically change them based on the environment, but unfortunately that does not work, as it hits the values that were originally in them.
webpack dev server has a proxy capability. You could use this to proxy to your locally running backend when developing.
https://webpack.js.org/configuration/dev-server/#devserver-proxy
e.g. you can point anything from '/api' to 'localhost:8888/api' with the config.
Is your app the backend running on the same url when deployed? If not, you'll likely need a reverse proxy to pass along the requests to the backend.
You can use an axios interceptor so you only have that switch in one place:
axios.interceptors.request.use(config => {
// check location.host name and append the backend url you want
});
see https://github.com/axios/axios#interceptors
However, this is a little dangerous as the URLs in your switch statement will be strings, and therefore all of your environment URLs can be pulled out of your code even if minified/concatenated.
Another option is to add some sort of endpoint to the server your client side code is hosted, and when you start your app, query for that configuration.