How to fetch() from public folder in NextJS? - javascript

I've got following use case scenario. I have web worker within which I need to fetch image that is located in NextJS public folder in order to convert it to blob.
Right now executing fetch('public/images/myImage.png'); or fetch('/images/myImage.png'); leads to an error:
Error: TypeError: Failed to execute 'fetch' on 'WorkerGlobalScope':
Failed to parse URL from /images/ui/background_fire.jpg
So I assume it is not being resolved correctly like it would in say src of an image?

#NasiruddinSaiyed answer is a bit outdated so here is the 2021 answer:
NextJS server-side-polyfills docs
Server-Side Polyfills
In addition to fetch() on the client side, Next.js polyfills fetch() in the Node.js environment. You can use fetch() on your server code (such as getStaticProps) without using polyfills such as isomorphic-unfetch or node-fetch.
So it should just work out of the box

As per official Docs you need to use isomorphic-unfetch.
It's a simple implementation of the browser fetch API, but works both in client and server environments.
Install it
$npm install --save isomorphic-unfetch
or
$yarn add isomorphic-unfetch
Now you can use it in from getInitialProps to any where in your component.
Example ::
`import fetch from 'isomorphic-unfetch';`
// ... Index component code
Index.getInitialProps = async function() {
const res = await fetch('https://api.tvmaze.com/search/shows?q=batman');
const data = await res.json();
console.log(`Show data fetched. Count: ${data.length}`);
return {
shows: data.map(entry => entry.show)
};
};
Happy coding!!

Related

Integrating node modules and JavaScript into our Web API controller calls

Our main backend server is a .net 5 web API project. I'm needing to integrate some javascript modules and javascript code into our functionality. I'm wanting to save on the time of rewriting these modules all into c# to access from our code. Are there any packages or methods to accomplish this or am I best of running a separate node server for this functionality?
Option 1. Access A Node.js Server Script From C#/.Net 5
Jering.Javascript.NodeJS enables you to invoke javascript in a Node.js module from C#. With this ability, you can use Node.js scripts/modules from within your C# projects. Supports: Callbacks, Promises and Async/Await. Get js scripts via file path, string or stream. You can run a single global instance of your Node.js App that remains in memory or create a new instance for each call. See an example on Invoking Javascript From File.
Install Via Package Manager or .Net CLI
Install-Package Jering.Javascript.NodeJS
#or
dotnet add package Jering.Javascript.NodeJS
some-module.js
module.exports = {
doSomething: (callback, message) => callback(null, { message: message + '!' }),
doSomethingElse: (callback, message) => callback(null, { message: message + '.' })
}
In your .Net App
var services = new ServiceCollection();
services.AddNodeJS();
ServiceProvider serviceProvider = services.BuildServiceProvider();
INodeJSService nodeJSService = serviceProvider.GetRequiredService<INodeJSService>();
public class Result {
public string? Message { get; set; }
}
Result? result = await nodeJSService.InvokeFromFileAsync<Result>("some-module.js", "doSomething", args: new[] { "success" });
Assert.Equal("success!", result?.Message);
This is a basic implementation example. You should see the Jering.Javascript.NodeJS Docs for complete examples of installation, configuration and usage.
Option 2. HTTP REST / Web Socket
Create an HTTP Rest or WebSocket Wrapper around your JS scripts and call them from the .Net App. In your .Net App, use HttpClient class to make HTTP requests. Then over in Node.js wrap your scripts with routes to access various methods. Something like:
const express = require('express');
const app = express();
const port = 3000;
app.get('/some/endpoint', (req, res) => {
// Gets executed when the URL http://localhost:3000/some/endpoint
// Do your thing here
// Return it back to .Net with:
res.send(JSON.stringify({some_response: "Hello There"}))
});
// Start the http server
app.listen(port, () => {
console.log(`Example app listening on port ${port}`)
});
Using the HTTP Rest/WebSocket option will require that you already have your node.js app running (and keep it running) before you attempt to call the endpoints from .Net.
Option 3. Execute Standard Javascript Embedded Scripts
Here are the most popular .Net modules that will allow you to run Standard Javascript code within your C# .Net Service. However, these both execute your JS Scripts using the V8 Engine and will not work for Node.js specific methods such as FileSystem. These will also not allow the use of require() or Import. This might be a good option if you have very limited Javascript needs and will not be adding additional JS functions in the future.
Microsoft.ClearScript
Jint
Javascript.Net
This option is quick and simple for very small scripts, but would be the most difficult to update and maintain your JS scripts.

ServerRuntimeConfig is empty

I am working on my nextjs project under docker, and when using getStaticProps my backend api is not available(which is also under docker). So I connected frontend to backend via networks and if i hardcode api for ssr request it works. But when i try to utilize serverRuntimeConfig and publicRuntimeConfig so i could switch between them depending on where code is being ran I get {} for serverRuntimeConfig. However publicRuntimeConfig is fine and i can access api from it.
My next.config.js is:
module.exports = {
publicRuntimeConfig: {
// Will be available on both server and client
baseUrl: 'http://localhost/api/v1',
},
serverRuntimeConfig: {
// Will only be available on the server side
baseUrl: 'http://backend_nginx_1/api/v1/',
},
am I missing something ?
This will sound dumb, but I spent 2 hours seeing the empty file been recognized by the system and just seeing {}.
Now... restarting the server, gives you access to the content of the file.
That was my solution.
And it was not included in the documentation.
https://nextjs.org/docs/api-reference/next.config.js/runtime-configuration

"_ssgManifest.js" & _buildManifest.js missing from a nextjs app hosted on Google Cloud Platform

sometimes the console shows these errors on opening the website
GET https://example.com/subpath/_next/static/9ufj5kFJf/_buildManifest.js
[HTTP/3 404 Not Found 311ms]
GET https://example.com/subpath/_next/static/9ufj5kFJf/_ssgManifest.js
[HTTP/3 404 Not Found 334ms]
Loading failed for the <script> with source “https://example.com/subpath/_next/static/9ufj5kFJf/_buildManifest.js”. 1434-247:1:1
Loading failed for the <script> with source “https://example.com/subpath/_next/static/9ufj5kFJf/_ssgManifest.js”.
the app does use ISR and that seems to be working, it does get updated, what do these files do? what could happen if they are missing?
"react": "17.0.2"
"next": "10.1.3",
"node" "15.1.2"
I had the same problem with GCP (Kubernetes engine) with pods count > 1. I resolved the issue by restarting the deployment (all pods).
On that Github issue #Prabir linked to in a comment, someone posted a way to use the generateBuildId function within the Next.js config file:
const execSync = require("child_process").execSync;
const lastCommitCommand = "git rev-parse HEAD";
module.exports = {
async generateBuildId() {
return execSync(lastCommitCommand).toString().trim();
},
};
I work with an app that uses some combination of AWS CodeBuild and Docker images, which prevents direct access to all the git commands so that snippet above didn't work. But using CODEBUILD_BUILD_ID or really any environment variable (unique to either that commit or the build itself) did. I'm not as familiar with the GCP-equivalents but this Cloud Build Docs page makes it seem like $COMMIT_SHA would be a good option to try.

Load local file using Netlify functions

I've written a script which takes a JSON file and outputs it to an API endpoint using Netlify's Functions feature (https://functions.netlify.com/). For the most part, this works without a hitch, however, one of my endpoints has a lot of text and for ease of editing, I've split the large text blocks into markdown files which I then loaded into the endpoint.
Locally, this works perfectly, but when deployed I get a console error saying Failed to load resource: the server responded with a status of 502 (). I presume this is because I used a node fs method and Netlify doesn't allow that, however, I can't find any information about this.
The code I've used is here:
const marked = require('marked')
const clone = require('lodash').cloneDeep
const fs = require('fs')
const resolve = require('path').resolve
const data = require('../data/json/segments.json')
// Clone the object
const mutatedData = clone(data)
// Mutate the cloned object
mutatedData.map(item => {
if (item.content) {
const file = fs.readFileSync(resolve(`./src/data/markdown/${item.content}`), 'utf-8')
item.content = marked(file)
}
})
exports.handler = function(event, context, callback) {
callback(null, {
statusCode: 200,
body: JSON.stringify({data: mutatedData})
});
}
I've also attempted to replace
const file = fs.readFileSync(resolve(`./src/data/markdown/${item.content}`), 'utf-8')
with
const file = require(`../data/markdown/${item.content}`)
but that complains about a loader and I'd like to avoid adding webpack configs if possible as I'm using create-react-app, besides, I doubt it will help as I'd still be accessing the file-system after build time.
Has anyone else come across this issue before?
At the time when this answer is written (September 2019), Netlify does not seem to upload auxiliary files to AWS Lambda, it appears that only the script where the handler is exported will be uploaded. Even if you have multiple scripts exporting multiple handlers, Netlify seems to upload them into isolated "containers" (different AWS instances), which means the scripts will not be able to see each other in relative paths. Disclaimer: I only tested with a free account and there could be settings that I'm not aware of.
Workaround:
For auxiliary scripts, make them into NPM packages, add into package.json and require them in your main script. They will be installed and made available to use.
For static files, you can host them on Netlify just like before you have AWS Lambda, and make http requests to fetch the files in your main script.

Loading weather API data into electron App

I started a project with my raspberry pi running an electron App where I need to get the actual weather from an open weather API. I am totally new to electron and not that experienced in Javascript. So I am stuck with getting the Data from the weather API into the App. I can request the Data as JSON or XML data. I tried out different ways I thought it might work but they all failed. So could someone tell me how to get API Data into electron in general?
The easiest way to start with API requests is to use axios.
After setting up the project (you can follow Getting Started), follow these steps:
Install Axios npm install --save axios
Create main.js in your project's folder.
Load main.js inside index.html somewhere before </body>.
Put the JavaScript code inside main.js
const axios = require('axios');
function fetchData() {
// you might need the next line, depending on your API provider.
axios.defaults.headers.post['Content-Type'] = 'application/json';
axios.post('api.example.com', {/* here you can pass any parameters you want */})
.then((response) => {
// Here you can handle the API response
// Maybe you want to add to your HTML via JavaScript?
console.log(response);
})
.catch((error) => {
console.error(error);
});
}
// call the function to start executing it when the page loads inside Electron.
fetchData();

Categories

Resources