Next JS and Vercel - development vs production - javascript

I’ve built a basic movie DB app in Next JS to see how the framework works. It’s an app that allows you to perform CRUD operations to firebase, utilising the NextJS API endpoints.
I have the app working fine in development, however it does not work at all once to Vercel. I was wondering if anyone can shed some light?
Here is the first 'get all data' call upon initialisation. The other API calls follow the same pattern. None work once deployed.
My index page has this getInitialProps function…
Home.getInitialProps = async () => {
const categories = await getCategories()
const movies = await getMovies()
const images = movies.map(movie => {
return {
id: `image-${movie.id}`,
url: movie.cover,
name: movie.name
}
})
return {
movies,
images,
categories
}
}
This fires off the getMovies function here…
export const getMovies = async () => {
const res = await axios.get('http://localhost:3000/api/movies')
return res.data
And the API endpoint it hits looks like this…
import firebase from '../../lib/firebase';
export default async(req, res) => {
const moviesRef = firebase
.collection('movies');
const snapshot = await moviesRef.get();
const movies = [];
snapshot.forEach(doc => {
movies.push({ id: doc.id, ...doc.data() })
})
res.json(movies)
Thanks in advance!

you should use your server link, not localhost.

You shouldn't hardcode http://localhost:3000 in the request's URL. You should omit it altogether since you're using Next.js API routes (same-origin).
export const getMovies = async () => {
const res = await axios.get('/api/movies')
return res.data
}
Edit: The above solution would work with API routes if the request was happening on the client-side only.
Since the request is made in getInitialProps, you should simply move the logic in your API route to a separate function (could very well be getMovies in this case) and call that directly in getInitialProps instead.
export const getMovies = async () => {
const moviesRef = firebase.collection('movies');
const snapshot = await moviesRef.get();
const movies = [];
snapshot.forEach(doc => {
movies.push({ id: doc.id, ...doc.data() })
});
return movies;
}

Related

NextJS ISR unlimited reload page when deployed to Vercel

I have a problem that my website being deployed to Vercel with NextJS ISR. When I use getStaticPaths. The website will reload unlimited when I click to getStaticPaths that page.
Only getStaticProps will not make this error. I am using the hobby plan. Everything works when I am on localhost and use "npm run build and start".
here is my code:
export async function getStaticProps({ params: { slug } }) {
const res = await fetch(`${API_URL}/post/${slug}`);
const posts = await res.json();
return {
props: {
posts,
},
// Next.js will attempt to re-generate the page:
revalidate: 10, // In seconds
};
}
export async function getStaticPaths() {
// this URL is created specifically for fetch first time of ISR
// My first post will unlimited reload**********
const res = await fetch(`${API_URL}/postforisrfirst`);
// const res = await fetch(`${API_URL}/post`);
const posts = await res.json();
// Get the paths we want to pre-render based on posts
const paths = posts.map((post) => ({
params: { slug: post.slug },
}));
return { paths, fallback: "blocking" };
}

How can I get user data from the stripe api with getServerSideProps in Next.JS?

I am trying to get some user data from stripe in the getServerSideProps function in Next.JS so that I can pass it down to some other components but I am having a hard time obtaining the data from the getServerSideProps function.
Below is my getServerSideProps function:
export const getServerSideProps = withPageAuthRequired({
async getServerSideProps(context) {
const user = getSession(context.req, context.res).user
const resources = await table.select({}).all()
const customer = await fetch(`/api/customers`).then(res => res.json()).then(data => {
data.data.find(user_data => user_data.metadata['auth0_user_id'] === user.sub);})
const subscriber_status = await customer.metadata['subscription_status'] === 'true';
return {
props: {
tech_resources: minifyRecords(resources),
subscriber_stats: subscriber_status, // I want to return the subscriber status so that I can pass it to another component later on
}
}
}
});
Below is my original fetch request which obtains the data I am looking for If I use it as a standalone function or with a useEffect hook.
fetch(`/api/customers`).then(res => res.json()).then(data => {
const customer = data.data.find(user_data => user_data.metadata['auth0_user_id'] === user.sub);
if (customer.metadata['subscription_status'] === 'true') {
// Do Something;}}
However, when I tried this inside of getServerSideProps it does not seem to work. Can anyone help me out on this?
The await fetch then using the promise looks strange to me.
When you use await, then your result will be the response.
So maybe try
const response = await fetch(`/api/customers`);
const data = await response.json();

TypeError: Only absolute URLs are supported on strapi app deployed on Heroku

I have a nextjs app with a strapi api deployed with heroku and the frontend with firebase. I use an environnement variable to fetch my api. It worked well in localhost but not with Heroku. I get the error: Only absolute URLs are supported**
I tried to hardcode my api URL, but I guess this is not the very best solution
Does someone ever meet that kind of problem ?
> Build error occurred
TypeError: Only absolute URLs are supported
at getNodeRequestOptions (/Users/mac/Documents/Website/strapi/strapi-starter/strapi-starter-next-ecommerce/frontend/node_modules/next/dist/compiled/node-fetch/index.js:1:64341)
at /Users/mac/Documents/Website/strapi/strapi-starter/strapi-starter-next-ecommerce/frontend/node_modules/next/dist/compiled/node-fetch/index.js:1:65715
at new Promise (<anonymous>)
at fetch (/Users/mac/Documents/Website/strapi/strapi-starter/strapi-starter-next-ecommerce/frontend/node_modules/next/dist/compiled/node-fetch/index.js:1:65650)
at fetchAPI (/Users/mac/Documents/Website/strapi/strapi-starter/strapi-starter-next-ecommerce/frontend/.next/server/pages/books/[name].js:7040:26)
at getProducts (/Users/mac/Documents/Website/strapi/strapi-starter/strapi-starter-next-ecommerce/frontend/.next/server/pages/books/[name].js:7053:26)
at getStaticPaths (/Users/mac/Documents/Website/strapi/strapi-starter/strapi-starter-next-ecommerce/frontend/.next/server/pages/books/[name].js:6997:60)
at buildStaticPaths (/Users/mac/Documents/Website/strapi/strapi-starter/strapi-starter-next-ecommerce/frontend/node_modules/next/dist/build/utils.js:17:86)
at Object.isPageStatic (/Users/mac/Documents/Website/strapi/strapi-starter/strapi-starter-next-ecommerce/frontend/node_modules/next/dist/build/utils.js:24:555)
at execFunction (/Users/mac/Documents/Website/strapi/strapi-starter/strapi-starter-next-ecommerce/frontend/node_modules/jest-worker/build/workers/processChild.js:155:17) {
type: 'TypeError'
}
api.js
export function getStrapiURL(path) {
return `https://intense-beyond-59367.herokuapp.com${path}`;
}
// Helper to make GET requests to Strapi
export async function fetchAPI(path) {
const requestUrl = getStrapiURL(path);
const response = await fetch(requestUrl);
const data = await response.json();
return data;
}
export async function getCategories() {
const categories = await fetchAPI("/categories");
return categories;
}
export async function getCategory(slug) {
const categories = await fetchAPI(`/categories?slug=${slug}`);
return categories?.[0];
}
export async function getProducts() {
const products = await fetchAPI("/books");
return products;
}
export async function getProduct(name) {
const products = await fetchAPI(`/books?name=${name}`);
return products?.[0];
}

Cloud Firestore working fine with .get() but not with .onSnapshot() using next.js

I'm having some trouble that I'm not understanding very well playing with next.js and Firebase's Cloud Firestore, but basically this works:
export async function fetchBroadcasts() {
const db = await loadDB();
const firestore = db.firestore();
const settings = { timestampsInSnapshots: true };
firestore.settings(settings);
return await firestore.collection('broadcasts').doc('message').get().then(doc => ({ broadcast: doc.data() }));
}
and this doesn't:
export async function fetchBroadcasts() {
const db = await loadDB();
const firestore = db.firestore();
const settings = { timestampsInSnapshots: true };
firestore.settings(settings);
return await firestore.collection('broadcasts').doc('message').onSnapshot(doc => ({ broadcast: doc.data() }));
}
I can't figure out why the second option doesn't work since I'm basically following the documentation.
On my index.js page I have this:
static async getInitialProps() {
return fetchBroadcasts();
}
onSnapshot doesn't return a promise, so you can't await it. As you can see from the linked API docs, it returns a function that you call when you want to stop the listener that you just added.
You use onSnapshot when you want to set up a persistent listener on a document that constantly receives changes to that document. You use get when you want a single snapshot of that document.
Firestore's onSnapshot() always return documents array regardless of query you use:
firestore.collection('broadcasts').doc('message')
.onSnapshot(docs => {
return docs[0].data();
});
While in case of get you can get single document as well on the base of query:
firestore.collection('broadcasts').doc('message')
.get( doc => ({ broadcast: doc.data() }) );

Make a http call with axios in the nuxtServerInit action

I'm working on a static website fetching content from the WordPress API.
On the menu of the website, I want the content to be save on a nuxt store, and available on the nav component.
I reed the doc of the nuxt server and the nuxtServerInit action, but I didn't find a nice example of how to make a axion call inside this action, and be able to fetch the store on the component.
I find this, but it's not working .. https://github.com/nuxt/nuxt.js/issues/2307
Thanks a lot for your help.
Try this
store/index.js
export const state = () => ({
data: null
})
export const actions = {
// nuxtServerInit is called by Nuxt.js before server-rendering every page
async nuxtServerInit({ commit, dispatch }) {
await dispatch('storeDispatchFunc')
},
// axios...
async storeDispatchFunc({ commit }) {
const { data } = await this.$axios.get('/api/wp....')
commit('SET_DATA', data)
},
}
export const mutations = {
SET_DATA(state, theData) {
state.data = theData
}
}

Categories