using Nuxt for server-side-rendering just for one page - vue.js

I have panel is developed by vuejs and vuetify that uses of v-router for managing routes in client-side, actually I had developed approximately 70% of my panel and in and due to the final change, I have to handle the server post request only to return from the payment page.
I want to use NUXT for SSR, but the problem is that NUXT ignores all my past routes because it does not have these routes itself.
My question is, can NUXT only be used to load just one page after server request to client while my panel work properly in the client-side?
I am new to web programming and I hope I have asked the right question. Anyway, thank for all your helps.
I added nossr.vue in pages directory without index.vue file(This is the only component in this directory and the rest of my vue components are placed in the Components directory).
I use of [https://stackoverflow.com/questions/54289615/how-to-read-post-request-parameters-in-nuxtjs][1] for custom middleware and post request handle class.
Here is postRequestHandle.js:
const querystring = require('querystring');
module.exports = function (req, res, next) {
let body = '';
req.on('data', (data) => {
console.log("post request data",data)
body += data;
});
req.on('end', () => {
req.body = querystring.parse(body) || {};
console.log("post request handler",req.body)
next();
});
};
and nuxt.config.js
export default {
devServer: {
host: 'mypanel.test.net',
port: 8080,
disableHostCheck: true,
hotOnly: true,
},
serverMiddleware: [
{ path: '/clickout', handler: './server-middleware/postRequestHandler.js' },
],
layout(context) {
return 'nossr'
}
}

Create an extra layouts in Nuxt called nossr.vue, make it's first element a <client-only> element. On every page except the SSR rendered page you put this:
export default {
layout: 'nossr'
}
For more information regarding layouts in Nuxt, please look at this https://nuxtjs.org/guides/directory-structure/layouts/

You can disable SSR for every page except your particular page by setting res.spa = true in the serverMiddleware
export default function(req, res, next) {
if (req.url !== '/clickout') {
res.spa = true;
}
next();
}
See also:
Nuxt Issue: Per-route ssr

Related

How to make NextAuth.js work with SSG (static site generated) in a Next.js website

Next.js allows you to build your site with either server-side (SSR) or static client-side (SSG) rendering, but when you run next build && next export it removes the /api routes.
Since NextAuth.js relies on these routes to for /api/auth/signin for example, how can you implement NextAuth.js for SSG?
Yes next-auth can validate both backend and frontend.
The function you want is getSession() which is available both on the backend and frontend. However you cannot do that with statically generated sites, as they are evaluated on build. You can do that with serverside rendering though.
Here is a sample Server Side rendered Page Auth Guard
export async function getServerSideProps(context) {
const session = await getSession(context);
if (!session) {
return {
redirect: {
permanent: false,
destination: "/login",
},
};
}
return {
props: {
session,
},
};
}
Here is a sample API auth
import { getSession } from "next-auth/client"
export default async (req, res) => {
const session = await getSession({ req })
/* ... */
res.end()
}

Vue router allways redirecting to error page

i am trying to setup a redirect when the user is not logged in. But when i do it like in my example the URL changes but i get This page could not be found from nuxt. The code is inside an login.js inside the plugins folder. Then i included this in the nuxt config like this.
plugins: [
'~/plugins/login.js'
],
And here is the actual code for handling redirecting
export default ({ app, store }) => {
app.router.beforeEach((to, from, next) => {
const loggedIn = store.state.account.loggedInAccount
if (!loggedIn) {
if (to.path !== '/redirect') {
next({ path: '/redirect' })
} else {
next()
}
} else {
next()
}
})
}
It looks like the routes are not mounted yet.
You should try to use middleware. It is the conventional way to implement the beforeEach function as mentioned by the official docs. You can read about it from here. If have access to the route object, store object and redirect function inside the middleware, so use redirect to direct to the other routes after validation.

How can I fix nuxt js static site links leading to network error?

I have a very basic nuxt.js application using JSON in a local db.json file, for some reason the generated static site links leading to network error, but I can access them from the url or page refresh.
nuxt config
generate: {
routes () {
return axios.get('http://localhost:3000/projects')
.then((res) => {
return res.data.map((project) => {
return '/project/' + project.id
})
})
}
},
main root index page
data() {
return {
projects: []
}
},
async asyncData({$axios}){
let projects = await $axios.$get('http://localhost:3000/projects')
return {projects}
}
single project page
data() {
return {
id: this.$route.params.id
}
},
async asyncData({params, $axios}){
let project = await $axios.$get(`http://localhost:3000/projects/${params.id}`)
return {project}
}
P.S. I have edited the post with the code for the main and single project page
Issues with server-side requests of your application are caused by conflicts of ports on which app and json-server are running.
By default, both nuxt.js and json-server run on localhost:3000 and requests inside asyncData of the app sometimes do not reach correct endpoint to fetch projects.
Please, check fixed branch of your project's fork.
To ensure issue is easily debuggable, it is important to separate ports of API mock server and app itself for dev, generate and start commands.
Note updated lines in nuxt.config.js:
const baseURL = process.env.API_BASE_URL || 'http://localhost:3000'
export default {
server: {
port: 3001,
host: '0.0.0.0'
},
modules: [
['#nuxtjs/axios', {
baseURL
}]
],
generate: {
async routes () {
return axios.get(`${baseURL}/projects`)
.then((res) => {
return res.data.map((project) => {
return '/project/' + project.id
})
})
}
}
}
This ensures that API configuration is set from a single source and, ideally, comes from environmental variable API_BASE_URL.
Also, app's default port has been changed to 3001, to avoid conflict with json-server.
asyncData hooks have been updated accordingly to pass only necessary path for a request. Also, try..catch blocks are pretty much required for asyncData and fetch hooks, to handle error correctly and access error specifics.

CORS axios Nuxt.js

I'm using an API with my Nuxt, here is my nuxt.config.js to allow the requests :
axios: {
prefix: '/api/',
proxy: true,
},
proxy: {
'/api/': {
target: process.env.API_URL || 'http://localhost:1337',
pathRewrite: {
'^/api/': '/',
}
},
}
On a specific page of my app, I need to send requests to another API from another domain. I'm using axios direclty in this Vue component :
axios.post('mysite.com/widget.rest')
As response, I obtain CORS error. Can I allow multiple API in my config ?
If you mean being able to access APIs under different URLs, AFAIK it's not possible out of the box. We tried adding proxy to different targets, but it only worked on client side, not during SSR.
What we ended up doing is having the default axios instance for our main API, and creating a plugin that creates extra axios instances for our other APIs for SSR.
Add extra "suburl" to proxy - this sorts out client side and means no CORS issues.
proxy: {
'/forum/': {
target: 'https://other.domain.com/',
pathRewrite: {'^/forum/': '/'}
},
'/api/': ...
},
For SSR to work, axios should hit directly the other API
import Vue from 'vue'
var axios = require('axios');
const forumAxios = axios.create(process.client ? {
baseURL: "/"
} : {
baseURL: 'https://other.domain.com/'
});
// this helps Webstorm with autocompletion, otherwise should not be needed
Vue.prototype.$forumAxios = forumAxios;
export default function (context, inject) {
if (process.server) {
forumAxios.interceptors.request.use(function (config) {
config.url = config.url.replace("/forum/", "");
return config;
}, function (error) {
return Promise.reject(error);
});
}
inject('forumAxios', forumAxios);
In components, you can then use something like:
async asyncData({app}) {
let x = await app.$forumAxios.get("/forum/blah.json");
You can use process.env prop of course instead of hardcoded URL.
This will hit https://other.domain.com/blah.json.

Nuxt custom module hooks not called

I want to pass some extra data from the ssr server that's present after the middleware has run, and use that on client side middleware. A bit similar to what nuxt already does with vuex.
Documentation at the render:context hook:
Every time a route is server-rendered and before render:route hook. Called before serializing Nuxt context into window.__NUXT__, useful to add some data that you can fetch on client-side.
Now my custom plugin defines some hooks as stated in the documentation, but not all seem to be called properly:
module.exports = function() {
this.nuxt.hook('render:route', (url, result, context) => {
console.log('This one is called on every server side rendering')
}
this.nuxt.hook('renderer', renderer => {
console.log('This is never called')
}
this.nuxt.hook('render:context', context => {
console.log('This is only called once, when it starts loading the module')
}
}
What am I doing wrong and how can I pass custom ssr data to the client side renderer?
Ok, just found the solution to the core problem of passing custom data from the (ssr) server to the client:
Create a plugin: plugins/my-plugin.js
export default ({ beforeNuxtRender, nuxtState }) => {
if (process.server) {
beforeNuxtRender(({ nuxtState }) => {
nuxtState.myCustomData = true
})
} else {
console.log('My cystom data on the client side:', nuxtState.myCustomData)
}
}
Then register the plugin in your nuxt.config.js:
module.exports = {
plugins: ['~/plugins/my-plugin']
}
Docs here.