After Nuxt build api returns 404 - vue.js

I'm having this weird issue and I seriously need your help. In development my code works perfectly fine but after doing nuxt build and all the apis are returning 404 error. Please help
When I'm building the api and running it, it works. In development api and nuxt both works but building nuxt and the api, doesn't work.
Following are my configuration
Server configuration
import convert from 'koa-convert';
import cors from 'kcors';
import bodyParser from 'koa-body';
import session from 'koa-session';
import helmet from 'koa-helmet';
import config from 'config';
import serve from 'koa-static';
import mount from 'koa-mount';
import { cModules, cMiddleware } from '../app';
import { catchErr, statusMessage } from './errorConfig';
import nuxtConfig from './nuxtConfig';
function baseConfig(app, io) {
app.keys = config.get('secret');
app.proxy = true;
app.use(mount('/static', serve(config.get('paths.static'))));
app.use(convert.compose(
catchErr,
cors({
credentials: true,
origin: true
}),
bodyParser({
multipart: true,
formLimit: '200mb'
}),
session({
maxAge: 21600000
}, app),
helmet(),
statusMessage
));
cModules(app, io);
app.use(cMiddleware());
if (config.get('nuxtBuild')) {
nuxtConfig(app);
}
}
export default baseConfig;
And my Nuxt
import { Nuxt, Builder } from 'nuxt';
import koaConnect from 'koa-connect';
import isDev from 'isdev';
import config from '../../../nuxt.config';
async function nuxtConfig(app) {
const nuxt = new Nuxt(config);
if (isDev) {
await new Builder(nuxt).build();
}
const nuxtRender = koaConnect(nuxt.render);
app.use(async (ctx, next) => {
await next();
ctx.status = 200;
ctx.req.session = ctx.session;
await nuxtRender(ctx);
});
}
export default nuxtConfig;

Related

How to setup multiple clients in Vue apollo v4?

I have 2 different servers (graphql, rest) and trying to setup multiple clients in my vue app.
Here is my setup apollo.provider.js
import { ApolloClient, createHttpLink, InMemoryCache } from '#apollo/client/core'
import { RestLink } from 'apollo-link-rest';
import { provide } from 'vue'
import { ApolloClients } from '#vue/apollo-composable'
// HTTP connection to the API
const httpLink = createHttpLink({
uri: 'https://reqres.in/graphql'
})
// Set `RestLink` with your endpoint
const restLink = new RestLink({
uri: "https://reqres.in"
});
// Cache implementation
const cache = new InMemoryCache()
// Create the graphql client
const graphqlClient = new ApolloClient({
cache: cache,
link: httpLink
})
// Create the rest client
const restClient = new ApolloClient({
cache: cache,
link: restLink
})
export const provider = provide(ApolloClients, {
default: graphqlClient,
restClient: restClient
})
This is not working, however I can use each client seperately by doing
import { createApolloProvider } from '#vue/apollo-option'
export const provider = createApolloProvider({
defaultClient: graphqlClient // or restClient
})
Please help me understand how to use both clients.
It turned out I mixed up between "options API" and "composition API"
considering my setup uses "options API" this solution works.
export const provider = createApolloProvider({
clients: {
graphqlClient,
restClient
},
defaultClient: graphqlClient,
})

using Nuxt 3 with Nest

Currently we are able to build nuxt as following. But are unable to handle routes. We basically want to serve nuxt app from Nestjs.
import { NestFactory } from '#nestjs/core';
import { AppModule } from './app.module.js';
import { loadNuxt } from 'nuxt3';
import { buildNuxt, Resolver } from '#nuxt/kit';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
// Check if we need to run Nuxt in development mode
const isDev = process.env.NODE_ENV !== 'production'
// Get a ready to use Nuxt instance
const nuxt = await loadNuxt({ rootDir: 'src/client-app/' })
// Enable live build & reloading on dev
if (isDev) {
buildNuxt(nuxt)
}
await app.listen(3001);
}
bootstrap();
Following is next (react) equivalent code which is working and trying to achieve in Nuxt 3.
https://github.com/hnviradiya/contact-list/blob/e38a72167d5710fcc9f3ed9718fa9bfe8ebb7d00/src/server/client-app/client-app.service.ts#L25
import { Injectable } from '#nestjs/common';
import { ConfigService } from '#nestjs/config';
import { IncomingMessage, ServerResponse } from 'http';
import createServer, { NextServer } from 'next/dist/server/next';
#Injectable()
export class ClientAppService {
private nextServer: NextServer;
constructor(private configService: ConfigService) {}
async onModuleInit(): Promise<void> {
try {
this.nextServer = createServer({
dev: this.configService.get<string>('NODE_ENV') !== 'production',
dir: './src/client',
});
await this.nextServer.prepare();
} catch (error) {
console.error(error);
}
}
handler(req: IncomingMessage, res: ServerResponse) {
return this.nextServer.getRequestHandler()(req, res);
}
}
In nuxt 2 there were nuxt.render(req, res) or nuxt.renderRoute(route, context). But these methods are not available in nuxt3.
https://nuxtjs.org/docs/internals-glossary/nuxt/
So how to serve nuxt app through NestJs.
Following is the repo where nuxt 3 code is there but it is not serving nuxt app.
https://github.com/hnviradiya/nest-nuxt
while Nestjs is a great server, it's angular style #decorators and modular setup is too unlike Nuxt3's scaffold simplicity.
This conception feels like a bad idea.

Access privateRuntimeConfig in express server

I've installed the express-nuxt template and I was wondering how could I get access to the privateRuntimeConfig inside nuxt.config.js from express (API folder). One approach I thought about was to put the vars inside a .env file and then installing the dotenv package for the express server, but I think that using just Nuxt could be better.
We have done precisely this by importing the Nuxt config into the file that configures the Express app, and using defu to combine public and private runtime configs, as Nuxt itself does:
// nuxt.config.js
export default {
publicRuntimeConfig: {},
privateRuntimeConfig: { redis: { url: process.env['REDIS_URL'] } }
};
// api/index.js
import express from 'express';
import defu from 'defu';
import { createClient as createRedisClient } from 'redis';
const app = express();
import nuxtConfig from '../nuxt.config.js';
let runtimeConfig;
app.use((req, res, next) => {
if (!runtimeConfig) {
// Load Nuxt config once, at runtime
runtimeConfig = defu(nuxtConfig.privateRuntimeConfig, nuxtConfig.publicRuntimeConfig);
}
next();
});
// Subsequent middlewares will then be able to read from `runtimeConfig`
app.use((req, res, next) => {
const redisClient = createRedisClient({ url: runtimeConfig.redis.url });
next();
});
export default app;

(vue) Uncaught InternalError: too much recursion: failed to use axios

I met a weird problem, when I set up main.js and run the server, it shows me this error
and here is my code in main.js,
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import ElementPlus from 'element-plus';
import axios from 'axios'
import 'element-plus/lib/theme-chalk/index.css';
axios.defaults.baseURL = 'http://localhost:8000'
const app = createApp(App)
app.use(store)
app.use(router)
app.use(ElementPlus)
console.log('1111')
app.use(axios)
console.log('aaa')
app.mount('#app')
I set a console.log to track the error, the '1111' shows but 'aaa' never shows, so I can only know the error occurs in the line app.use(axios), that's so confusing, did anyone ever met this problem? How to solve it?
Here you have 2 options:
If you're using Vue3, import it in your Vue, like you did, but as written in this awnser, i think you should do something more like that:
import { createApp } from 'vue'
import axios from 'axios'
import VueAxios from 'vue-axios'
const app = createApp(App)
app.use(VueAxios, axios) // 👈
app.mount('#app')
You wanna use only axios and don't get bothered by it, then you don't have to use VueAxios or make something like app.use(axios) in your main.js, and then make a httpRequestsService file which will handle all the axios part.
For example, here is mine:
import axios from "axios";
axios.defaults.baseURL = process.env.API_BASE_URL
axios.interceptors.response.use(res => res, err => {
// some code if you wanna handle specific errors
throw err;
}
);
const getHeader = (method, endpoint, header, body) => {
const publicEndpoints = [
{
method: 'POST',
endpoint: '/auth/local'
}
]
const publicEndpoint = publicEndpoints.find(e => e.method === method && e.endpoint === endpoint)
if (!publicEndpoint) {
header.Authorization = localStorage.getItem("jwt")
}
return body ? { headers: header, data: body } : { headers: header }
}
export default {
get(endpoint, header = {}) {
return axios.get(endpoint, getHeader('GET', endpoint, header))
},
post(endpoint, body = {}, header = {}) {
console.log(body)
return axios.post(endpoint, body, getHeader('POST', endpoint, header))
},
put(endpoint, body = {}, header = {}) {
return axios.put(endpoint, body, getHeader('PUT', endpoint, header))
},
delete(endpoint, body = {}, header = {}) {
return axios.delete(endpoint, getHeader('DELETE', endpoint, header, body))
},
}

Why Morgan Logger server middleware doesn't work in separate file?

I am following this tutorial in my nextjs app for adding a new middleware for logging so I have the following code in my server.js:
// create a write stream (in append mode)
const accessLogStream = fs.createWriteStream(path.join(__dirname, 'access.log'), { flags: 'a' })
// setup the logger
server.use(morgan('combined', { stream: accessLogStream }))
And it is working without a problem.
But I want to have the logic in a separate file in the middleware directory so I have :
middlewares/logger/index.js
import morgan from "morgan";
import fs from 'fs';
import path from 'path';
export default (req, res, next) => {
var accessLogStream = fs.createWriteStream(path.join(__dirname, 'access.log'), { flags: 'a' })
return morgan('combined', { stream: accessLogStream });
};
and in my server.js I will have: (after importing and initializing stuff)
server.use(logger);
server.use(othermiddlewareone);
server.use(othermiddlewaretwo);
The other middlewares are working fine but this one breaks. Do you know why is that?
I changed the middleware like this and now it is working fine :)
import type { Request, Response, Next } from './types';
import morgan from "morgan";
import fs from 'fs';
import path from 'path';
const accessLogStream = fs.createWriteStream(path.join(__dirname, 'server.log'), { flags: 'a' })
const logger = morgan('combined', { stream: accessLogStream })
export default async (req: Request, res: Response, next: Next) => {
logger(req, res, function (err) {
return next();
})
};