NuxtJs generate for dynamic websites? - vue.js

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.

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.

Nuxt.js - Is it appropriate to use the "Generate" property with a large amount of users?

ok so I'm starting to use Nuxt in spa mode and I can see that dynamic pages work differently so I was searching and I found that I can use the generate property
to generate the dynamic pages when I start the production, but is it ok to use it if my API has too many users?? or is there a better way to create the dynamic pages??
This depends on whether or not your production site will be static or server-side rendered.
nuxt generate is used for target: static (bundles the site as plain, SEO-friendly html pages)
nuxt build is used for target: server with either ssr: set to true or false. This bundles the site as either a server side rendered site or a single page application (SPA) with exclusively client-side navigation.
Good summary here: https://kontent.ai/blog/demystify-nuxt-target-mode-and-ssr-properties
I don't see any big problems in scaling a Nuxt application. But obviously involving server rendering will put some more strain on your server than a SPA or static jamstack-site with plain, prebuilt html pages.
If you don't need the SEO, then I would go for the SPA option with ssr: false. Super fast and requires minimal server resources on your end after the site has loaded on the client machine.

Vue: How to enable multi page in an existing SPA project?

I have a single page (SPA) application written in Vue.
Now I need a separate page that should be available without being signed in.
To me it seems like a need to enable multi page app (MPA). I see in the documentation (https://cli.vuejs.org/config/#pages) that I need to set this up in vue.config.js. But I the documentation is unclear to me. Do I need to edit/rerun the Vue CLI setup? Or do some webpack changes. Just adding a new page entry with corresponding files does not work (webpack does not insert anything in html-file).
From SPA View, i would likely go like this
Inside /views folder
- HomePage.vue (no auth)
- Login.vue
- /users/ subfolder (auth needed)
- DashBoard.vue
- About.vue
etc
Then define the routes (paths,components,etc.) with requiresAuth as auth-check, redirects back to the route with HomePage.vuecomponent then.
and SPA mostly comes with MPA Challenges such as SEO, SSR concerns. The routing roughly the same to Vue/Nuxt.

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.

Using prerender.io with ReactJS for SEO

I've realized that my ReactJS application using react-router does not have any external links. Search engines do not recognize that the site has a lot of linked content. Prerender.io seems like a good solution to this, but I cannot get it to work for my ReactJS application.
Can prerender.io be used with ReactJS? If not, is there another good way to improve SEO for my site without doing all the rendering server-side?
EDIT: Upon further digging, I realized that the issue here is that react-router uses a "#" by default, and not a "#!". Is it possible to make react-router work with a "#!"?
Prerender appears to expect real urls, because otherwise you can't serve the cached html to normal people (the hash isn't sent to the server).
When setting up react-router ensure it's using the history mode:
Router.run(routes, Router.HistoryLocation, function (Handler) {
In your server you'll need to ensure that all routes that don't match a static file are served by either sending index.html, or using prerender.
You can search for 'send all requests to index.html {insert server name here}' to find details on this.
It seems that by default prerender only applies in certain situations. Here's an example if you're using the express.js middleware in node.js:
require('prerender-node').shouldShowPrerenderedPage = function(){ return true }
You should be able to figure out similar modifications for other middleware (it'll require a fork in less flexible languages).