This question already has an answer here:
Fetch error when building Next.js static website in production
(1 answer)
Closed last year.
Code is below, the dev server works perfectly fine without error, however when I try to deploy the site I get this error.
> Build error occurred
TypeError: artists.map is not a function
at getStaticPaths (/vercel/path0/.next/server/pages/artists/[slug].js:106:24)
at processTicksAndRejections (internal/process/task_queues.js:95:5)
at async buildStaticPaths (/vercel/path0/node_modules/next/dist/build/utils.js:498:31)
at async /vercel/path0/node_modules/next/dist/build/utils.js:641:119
at async Span.traceAsyncFn (/vercel/path0/node_modules/next/dist/trace/trace.js:74:20) {
type: 'TypeError'
}
export async function getStaticProps({ params }) {
const siteSettings = await fetcher("http://localhost:3000/api/settings");
const artists = await fetcher(
`${process.env.URL}/api/artists/${params.slug}`
);
const artist = artists.allArtist[0];
return {
props: {
siteSettings,
artist,
},
};
}
export async function getStaticPaths() {
const artists = await fetch(`${process.env.URL}/api/artists`);
return {
paths: artists.map((artist) => {
return {
params: {
slug: artist.slug.current,
},
};
}),
fallback: false,
};
}
How would I go about fixing this error, as I said it works perfectly fine in the dev server with no console logs containing any errors.
Any help would be greatly appreciated.
I attempted writing the API route logic directly in the getStaticProps function and this fixed the error #juliomalves also posted this link which suggests a similar answer: Fetch error when building Next.js static website in production
Thanks for the help.
Mac
Related
I have built an app using Nextjs and I am having the following problem when I try to deploy the app on Vercel. Npm run build always throws this error:
Error occurred prerendering page "/portfolio/0". Read more: https://nextjs.org/docs/messages/prerender-error
TypeError: jsonRes.items is not iterable (cannot read property undefined)
at /vercel/path0/.next/server/pages/portfolio/[id].js:84:150
at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
at async getPhotos (/vercel/path0/.next/server/pages/portfolio/[id].js:84:5)
at async getStaticProps (/vercel/path0/.next/server/pages/portfolio/[id].js:114:18)
at async renderToHTML (/vercel/path0/node_modules/next/dist/server/render.js:384:20)
at async /vercel/path0/node_modules/next/dist/export/worker.js:248:32
at async Span.traceAsyncFn (/vercel/path0/node_modules/next/dist/trace/trace.js:79:20)
I am trying to retrieve a gallery of photos from Google Drive that relate to the projects I need to display. I have followed the Next.js documentation to a T and my app works just fine locally and I have no errors when I run npm run build locally. The following is my code where the API call that returns undefined is located:
export async function getPhotos() {
const imgIds = [];
const URL_START = "https://www.googleapis.com/drive/example/url";
const URL_END = "example";
await fetch(URL_START + process.env.NEXT_PUBLIC_DIR_ID + URL_END + process.env.NEXT_PUBLIC_G_KEY)
.then(res => res.json())
.then(jsonRes => imgIds.push(...jsonRes.items));
return imgIds;
}
And the following is the getStaticProps function where the above function is called:
import { getPhotos } from '../../lib/photos';
export const getStaticProps = async (context) => {
const id = context.params.id;
const project = Projects.projects[id];
var photos = await getPhotos(); // function from lib/
var projectPhotos = [];
for (var i = 0; i < photos.length; i++) {
if (photos[i].title.includes(project.title)) {
projectPhotos.push(photos[i]);
}
}
project.images = projectPhotos;
return {
props: {
project
}
}
}
To see the documentation I referred to, go here: https://nextjs.org/docs/basic-features/data-fetching/get-static-props
Thank you in advance.
I've completed my first JavaScript course and am now following a course on React. I've created a simple backend using Express and MongoDB.
I've created a frontend using npx create-react-app, added axios to communicate with the backend and am using antd for the UI. So far so good! The following code works on my laptop running Windows 10 and Edge 94 to insert a new Year into MongoDB using a simple input:
Client uses:
const onFinish = async (values) => {
await api.createYear(values).then((res) => {
console.log("onFinish", values);
console.log(res);
});
};
API uses:
import axios from 'axios'
const api = axios.create({
baseURL: 'http://localhost:3000/api/v1',
})
export const createYear = values => api.post(`/year`, values)
Server (controller) uses:
const Year = require('../models/year-model')
createYear = (req, res) => {
const body = req.body
if (!body) {
return res.status(400).json({
success: false,
error: 'You must provide a year!',
})
}
const year = new Year(body)
if (!year) {
return res.status(400).json({ success: false, error: err })
}
year
.save()
.then(() => {
return res.status(201).json({
success: true,
id: year._id,
message: 'Year created!',
})
})
.catch(error => {
return res.status(400).json({
error,
message: 'Year not created!',
})
})
}
Server (model) uses:
const mongoose = require('mongoose')
const Schema = mongoose.Schema
const yearSchema = new Schema(
{
year: { type: Number, required: true }
},
{ timestamps: false },
)
module.exports = mongoose.model('Year', yearSchema)
However, the same code does not work on my Samsung Galaxy S21 using Edge 93 and Chrome 94. Based on what I found so far, this could be caused by this browser not supporting async/await (ES2017 feature). This could probably be resolved by Babel?
I'm sorry that this part is pretty vague: the information I found is a kind of overwhelming considering my limited experience and all variables involved (React version, Babel version, Babel plugins, Webpack etc). I would gladly provide more information if you could point me in the right direction.
Could anyone perhaps tell me if and how I should change Babel or Webpack to make async/await work in mobile browsers?
If the problem is that async/await doesn't work on those browsers, then I think you can change your .babelrc file to target older browsers.
However, to address #ammar's points, maybe double check that:
you can see web pages served by your laptop on your phone
your phone browser doesn't work with async/await
I would create a simple html page that looks like this to make sure that this is the problem.
<html>
<head></head>
<body>
<div>TEST PAGE<div>
<div id='test'></div>
<script>
function sleep(t) {
return new Promise(function(resolve) {
setTimeout(resolve, t);
});
}
(async function() {
for (let x = 0; x < 1000; x++) {
document.getElementById('test').innerHTML = x;
await sleep(1000);
}
})();
</script>
<body>
</html>
I would attack it like this:
save the above as test.html
open the file directly with your laptop browser and see the count-up
figure out how to serve the same file as static content with the webpack dev server, and open it in the laptop browser
open the same file on your mobile device to prove that you can see the page at all, and that async/await is not working
while deploying pub-sub code on firebase i'm getting following error :
ERROR: (gcloud.functions.deploy) OperationError: code=3, message=Function failed on loading user code. This is likely due to a bug in the user code. Error message: Code in file index.js can't be loaded.
Is there a syntax error in your code?
Detailed stack trace: /srv/node_modules/#google-cloud/pubsub/build/src/pubsub.js:527
async *listSchemas(view = schema_1.SchemaViews.Basic, options) {
^
I'm not getting why this error is occurring.
following is the code:
exports.publish = async (req, res) => {
if (!req.body.topic || !req.body.message) {
res.status(400).send('Missing parameter(s); include "topic" and "message" properties in your request.');
return;
}
console.log(`Publishing message to topic ${req.body.topic}`);
const topic = pubsub.topic(req.body.topic);
const messageObject = {
data: {
message: req.body.message,
},
};
const messageBuffer = Buffer.from(JSON.stringify(messageObject), "utf8");
try {
await topic.publish(messageBuffer);
res.status(200).send("Message published.");
} catch (err) {
console.error(err);
res.status(500).send(err);
return Promise.reject(err);
}
};
I'm going to guess that this function is set to use the Node 8 runtime, since support for async iterators was added in Node 10. The Pub/Sub library has only supported Node 10 and above since 2.0, so bumping the runtime version on the Firebase function should help:
https://firebase.google.com/docs/functions/manage-functions#set_nodejs_version
Unfortunately I don't have enough points to ask for more details on the original question, but hopefully that helps!
Describe the bug
I have built an application with NextJS that has an internal API and I use the getStaticProps methods to query the API.
You can find the deployed app here: https://tailor-challenge.vercel.app/
And also the github repository here: enter link description here
The application works perfectly in development mode and the deploy I made in Vercel also works. But when I run the next build command I get the following error:
Build error occurred
FetchError: request to http://localhost:3000/api/restaurants failed, reason: connect ECONNREFUSED 127.0.0.1:3000
at ClientRequest.<anonymous> (/home/silinde87/Jobs/tailor/TailorChallenge/node_modules/node-fetch/lib/index.js:1461:11)
at ClientRequest.emit (node:events:376:20)
at Socket.socketErrorListener (node:_http_client:474:9)
at Socket.emit (node:events:376:20)
at emitErrorNT (node:internal/streams/destroy:188:8)
at emitErrorCloseNT (node:internal/streams/destroy:153:3)
at processTicksAndRejections (node:internal/process/task_queues:80:21) {
type: 'system',
errno: 'ECONNREFUSED',
code: 'ECONNREFUSED'
}
info - Collecting page data .npm ERR! code 1
npm ERR! path /home/silinde87/Jobs/tailor/TailorChallenge
npm ERR! command failed
npm ERR! command sh -c next build
NextJS internal API
/api/restaurants/index.js
export default function handler(req, res) {
const { method } = req;
switch (method) {
case 'GET':
getRestaurants();
break;
default:
res.status(405).end(`Method ${req.method} Not Allowed`);
}
function getRestaurants() {
const restaurants = data;
res.status(200).json(restaurants);
}
}
/api/restaurants/[id].js
export default function handler(req, res) {
const { id } = req.query;
const { method } = req;
switch (method) {
case 'GET':
getRestaurantById();
break;
default:
res.status(405).end(`Method ${req.method} Not Allowed`);
}
function getRestaurantById() {
const restaurants = data.find((el) => el.id.toString() === id.toString());
if (restaurants) res.status(200).json(restaurants);
else res.status(405).end(`There is no Restaurant with id: ${id}`);
}
}
Pages from NextJS
pages/index.js <-- Where I fetch the restaurants list
export async function getStaticProps() {
const res = await fetch(`${process.env.NEXT_PUBLIC_NEXTAUTH_URL}/api/restaurants`);
const restaurants = await res.json();
if (!restaurants) {
return {
notFound: true,
};
}
return {
props: {
restaurants,
},
};
}
pages/[id].js
// Return a list of possible value for id
export async function getStaticPaths() {
const res = await fetch(`${process.env.NEXT_PUBLIC_NEXTAUTH_URL}/api/restaurants`);
const restaurants = await res.json();
let paths = restaurants.map(({ id }) => {
return {
params: {
id: id.toString(),
},
};
});
return { paths, fallback: false };
}
// Fetch necessary data for the restaurant details using params.id
export async function getStaticProps({ params }) {
const res = await fetch(`${process.env.NEXT_PUBLIC_NEXTAUTH_URL}/api/restaurants/${params.id}`);
const restaurantData = await res.json();
return {
props: {
restaurantData,
},
};
}
I took this quote from the official documentation, link below:
Note: You should not use fetch() to call an API route in >getStaticProps. Instead, directly import the logic used inside >your API route. You may need to slightly refactor your code for >this approach.
Fetching from an external API is fine!
https://nextjs.org/docs/basic-features/data-fetching
Basically because the code inside getStaticProps or getStaticPaths is never executed in the browser, so you can safely call the data source directly there.
Also the failure happens because the app is not running when building, so the localhost api is not available. You can confirm this by running the app via ’yarn dev’ or ’npm run dev’ in another terminal window, and building the app in another terminal window. This way it should build just fine, but it's not recommended way of doing it. I would refactor the code so that there is no fetch to the api of this app in those getStaticProps and getStaticPaths functions.
Same goes for getServerSideProps, that is also just run on the server, so you shouldn't be doing fetches to the api there either. Only the browser should do fetches to the api, for example if you want the user to be able to post some data to the app.
I'm running some webhooks on Netlify, but I'm getting an uncaught exception: Runtime.ImportModuleError.
Here is the full error, and you can access a snapshot of the function HERE
{"errorType":"Runtime.ImportModuleError","errorMessage":"Error: Cannot find module 'safe-buffer'\nRequire stack:\n- /var/task/src/node_modules/mqtt/lib/connect/ws.js
That is when I import 'async-mqtt', but the problem is that I have another function which uses the exact same import, without any problem. I can reproduce it on another function, but I'm not sure how I can go about reproducing it separately. I'm really lost, so ask if there is any information I need to explain.
Netlify runs on AWS functions, if that can help. Here is the full code of the function:
console.log('at least it opens');
const mqtt = require('async-mqtt');
exports.handler = async function (event, context) {
const client = await mqtt.connectAsync(
'mqtts://mqtt.flespi.io', {
username: 'SECRET HERE',
port: 8883,
clientId: `action-on-google--${Math.random().toString(16).substr(2, 8)}`,
},
);
await client.publish('lights/bulbs', 'N255,0');
client.end();
return { statusCode: 200, body: 'Hello world' };
};