I am currently building an app with React and Node.js
In this app, I need to query a database on my own server with the following function, located in a separate file called "database.js"
const fetchQuery = util.promisify(con.query).bind(con)
// Get all the tracks for a given date from the
const fetchTracks = async (date) => {
const rows = await fetchQuery("SELECT * FROM tracks WHERE playlistDate = '"+date+"'");
}
This works perfectly when I run the file with Node from the command line. However, when I attempt to import it into my react app with
import { fetchTracks, addTracks } from '../scripts/database'
I begin to get errors in the database file, specifically Unhandled Rejection (TypeError): Net.createConnection is not a function on my fetchQuery call.
From what I've read, this happens when attempting to call the function from the browser, as that would pose a security risk. However, as I understand it, all node operations are performed on the server side, right? Why would I be getting this flag when the database is supposedly queried before the page is served? What do I need to do amend this?
React runs in the browser, so as soon as you include database.js in your React app, it's running in the browser with the rest of React, so of course you'll get the error. Making this work gives two options:
expose an API endpoint from Node for React to call, and that API endpoint calls database.js, or,
investigate server-side rendering for React, where some of your React app -- particular the more static parts of it like your main menu -- are created on the Node side and only the final HTML is sent to the browser. (This is a large topic all by itself though.)
By your example which takes a date parameter for the SQL, I'm guessing #2 isn't an option.
Related
Trying to fetch my json file, but apparently the URL is invalid or wrong as per the warning.
Tried to console log modelURL and it looks correct. Console.log Output : ./tm-my-image-model/model.json
Full error
Uncaught Error: Request to ./tm-my-image-model/model.json failed
with status code 404
const URL = ./tm-my-image-model/;
let model, webcam, maxPredictions, happy, sad, angry;
let refresh = true;
async function init() {
if (refresh) {
refresh = false;
const metadataURL = URL + "metadata.json";
const modelURL = URL + "model.json";
console.log(modelURL)
}}
File Structure
How are you doing the fetch? (It is not in the code you provided).
In Node.js to work with the file system you need to use the native module fs.
Node.js v18.2.0 documentation File system
This depends where you're calling it from. Currently, the path is relative, and where it's relative to can get quite confusing quite quickly. Note that if you're able to send the path with the page render, that might be good too, since you can then resolve the path from node, and avoid any ajax.
That being said, if possible (since this looks to be node anyway), it would probably be a whole lot easier to use require("x") (or import x from "x" if ESM), or, if you need it to load asynchronously, using the await import("x") syntax.
If you're using server side rendering only, it may be useful to make a network call and fetch the file from your server asynchronously as well.
So this is a fairly new topic, React Server Components has recently been released, comparing to SSR/Next.js, how does it affect SEO?
Since the component is rendered in the server dynamically when it is requested, it is not really as static as SSR like Next.js, will search engine fail to index those component if I use it?
A demo can found here
We can see that in api.server.js,
async function renderReactTree(res, props) {
await waitForWebpack();
const manifest = readFileSync(
path.resolve(__dirname, '../build/react-client-manifest.json'),
'utf8'
);
const moduleMap = JSON.parse(manifest);
pipeToNodeWritable(React.createElement(ReactApp, props), res, moduleMap);
}
function sendResponse(req, res, redirectToId) {
const location = JSON.parse(req.query.location);
if (redirectToId) {
location.selectedId = redirectToId;
}
res.set('X-Location', JSON.stringify(location));
renderReactTree(res, {
selectedId: location.selectedId,
isEditing: location.isEditing,
searchText: location.searchText,
});
}
I understand this can help to reduce the workload for client's device, since the component are rendered on the server and sent to the client, and that the component can be rendered with the secret stored in server as we can just pass it in as props rather we sending the secret to client.
But if SEO matters, is SSR preferred over React Server Component?
Server Components are complementary to rendering into HTML, not an alternative. The plan is to have both.
Server Components were not released. What was released is an early tech preview in the spirit of sharing our research. This preview doesn’t include an HTML renderer. The api.server.js file from the demo you mentioned contains a comment about this:
const html = readFileSync(
path.resolve(__dirname, '../build/index.html'),
'utf8'
);
// Note: this is sending an empty HTML shell, like a client-side-only app.
// However, the intended solution (which isn't built out yet) is to read
// from the Server endpoint and turn its response into an HTML stream.
res.send(html);
By the time Server Components are officially released, there will be a streaming HTML renderer for the first render.
It’s not built yet.
It should be same from SEO point of view as SPA.
What happens with classic React SPA is, it loads React components (which are essentially JS functions) as part of the JS bundle, and then it starts to request data from the backend in JSON format. After JSON is fetched, it is rendered via the React component functions and inserted into the DOM. Modern crawlers use V8 engine (or maybe smth else if it's Bing :D), they wait until page is fully loaded and all JSON data is loaded and all components are actually rendered - and then it crawls the resulting DOM.
GoogleBot is crawling SPAs that way for at least 3 years now, probably more - so if you were thinking that SSR is essential for SEO, no, it is not. There were plenty of investigations into this, random example: https://medium.com/#l.mugnaini/spa-and-seo-is-googlebot-able-to-render-a-single-page-application-1f74e706ab11
So essentially for crawler it doesn't really matter, how exactly React component is rendered. In case of React Server Components, component function resides on server and is never transferred to the client as part of the JS bundle. So instead of requesting JSON data, the application requests rendered component in some intermediate format (not HTML btw). Result of that is transferred to the client and is getting rendered to the DOM. So the end result is still the same - it's some DOM elements that the bot can crawl.
I am trying to integrate the socket.io with React.js I am running socket.io on server with Express.js back end.
The problem is this I am on homepage and when order is placed from homepage then i am showing that order in the Orders page of React but the problem is it sometimes shows the order but it sometimes does not shows the order and if i open multiple tabs on different browsers then on some tabs in some browsers the order does not show mean the socket connection does not work some time but in all of the cases when ever a order is created from home page then the emit from the socket.io from home page is showing in the Node.js Express.js back end.
Please note I am using clustering module on the express.js
Here is how i am creating the socket.io connection.
socket = io('http://localhost:5000',{ reconnect: true ,transports: ['websocket']});
Here is my homepage react component from where i am placing the order.
socket.emit("putKitchenOrder", Order);
Here is my second component on which i want to show the order which is placed in real time using socket.io
componentWillUnmount(){
socket.off("kitchen-channel:orderPlacedFromPos");
}
componentDidMount() {
socket.on("kitchen-channel:orderPlacedFromPos", (order) => {
console.log('order in orderPlacedFromPos');
console.log(order);
alert('order in orderPlacedFromPos')
});
}
Here is my Node.js and Express.js code
io.on("connection", socket => {
socket.on("putKitchenOrder", order => {
// this console.log is always showing in the node.js console window when ever a new order is placed from the homepage component but the second page is not getting the following emit "kitchen-channel:orderPlacedFromPos" sometime.
console.log('putKitchenOrder order');
io.emit("kitchen-channel:orderPlacedFromPos",order);
});
});
The console.log('putKitchenOrder order'); is always showing in the node.js console window when ever a new order is placed from the homepage component but the second page is not getting the following emit "kitchen-channel:orderPlacedFromPos" sometime.
From what I know when you switch between components the components are mounted again. So maybe you can create a singleton for the socket instance like in this article, and put a log in the file where you create the socket, you can debug with that and also can be the solution
I'm new to node js and vue development and I want to create a process where I can create and upload a JSON file to my server when the user saves data in a form. This process should be done in the background. Later I want to read and update that file from the server when the user changed something.
So my first idea was to use fs.writeFile() this doesn't work very well and I think this only works for local stuff is that correct?
var fs = require('fs')
export default {
methods:{
send(){
fs.writeFile("/test.json","Hello World!",function(err){
if(err){
throw err;
}
});
}
}
}
Furthermore it looks like fs.writeFile doens't work with vue because it throws this error:
TypeError: fs.writeFile is not a function at VueComponent
So my second idea was to use express js with the app.post('/api/apps',...) and app.get() method. Here I have no idea how to implement that into the vue framework because I have to call the api like mydomain.com/api/apps but this doesn't work too.
So what is the best way to create, read, upload, delte files into a specific folder on my server? And how it works with vue? I tend to express js.
I'm using vue cli :)
Thanks in advance :)
EDIT
Now what I do is:
I created a new folder in my vue project root and named it "backend". In this folder I created a file named index.js and put this code
app.post('/appjson',(req,res) => {
fs.writeFile("/appjson/myJson.json",req.body,function(err){
//handle error
});
});
on the client side I put this code
axios.post('myDomain.com/appjson', {
JSONdata: myJSONdata,
})
My project looks like:
So when I build I get the dist folder and this I can upload on my server and it works fine. But I can't do the call to my backend? Whats wrong do I call the wrong link? Or how can I access my backend? Is the project struture correct or do I need to add the backend to a specific folder?
Vue is client side, your code is trying to write something to the filesystem of the user thats using your website. what you want to do is send this data to your NodeJS server, this requires using a package like Axios to send data to and from the server without refreshing the page. Axios is pretty straight forward to use, what you need will look similar to the function below.
saveJSON (myJSONData) {
const url = myNodeJSURL/savescene
return axios.post(url, {
JSONdata: myJSONdata,
})
Read some tutorials on ExpressJS, It's a pretty painless framework to use. You'll get the data stored in the body of the HTTP request and then you can use fs.writeFile to save data to the local filesystem of your server. Let me know if you need more help.
EDIT:
Your front end needs to be access a domain or IP address associated with your back end in order to communicate with it. Add the snippet below to your ExpressJS application and then when you run the server any requests to localhost:3000 will be handled by your app. You'll also have to update the URL in your Axios call.
app.listen(3000, function () {
console.log('my server is listening on port 3000!')
})
this setup only works for testing purposes because client and server will have to be on the same machine for localhost to mean the same to both. If you want this project to be public then you need to get your own domain for your site and host the ExpressJS application through there. Google compute makes this pretty easy to do, I'd look into that if I were you.
I'm using Next.js, and I have a custom server using Express. I have a page that requires some data from the database.
getInitialProps(), when running on the server, could just grab the data from the database and return it, without any problems.
However, getInitialProps() can also run on the client side (when the user initially requests a different page, then navigates to this one). In that case, since I'm on the client side, I obviously can't just fetch the data from the database - I have to use AJAX to talk to the server and ask it to retrieve it for me.
Of course, this also means that I have define a new Express route on the server to handle this request, which will contain exactly the same code as the server-side part of getInitialProps(), which is very undesirable.
What's the best way to handle this?
getInitialProps() always receives the request and response as parameters which are only set on the server:
static async getInitialProps({req}){
if(req){
// called on server
} else {
// called on client
}
}
https://github.com/zeit/next.js#fetching-data-and-component-lifecycle
Since no good solution seemed to have existed, I have created and published a library to provide a simple and elegant solution to this problem: next-express.
In your getInitialProps you should be making a http request to a new express route that has your logic for fetching from the database. That logic should never live in the UI layer.
This route should then be called regardless of whether you are on the client or on the server - you don't need to do any code branching.
Make an API distinct from your next.js app. Think of the next app as a frontend client that happens to render pages on the server
With time new solutions come around.
Nextjs has introduced a new method getServerSideProps primarily for such use cases
getServerSideProps only runs on server-side and never runs on the browser.
For me, the quickest way I found is to get the data from __NEXT_DATA__
MyApp.getInitialProps = async (): Promise<AppCustomProps> => {
const isInBroswer = typeof window !== 'undefined';
if (isInBroswer) {
const appCustomPropsString =
document.getElementById('__NEXT_DATA__')?.innerHTML;
if (!appCustomPropsString) {
throw new Error(`__NEXT_DATA__ script was not found`);
}
const appCustomProps = JSON.parse(appCustomPropsString).props;
return appCustomProps;
}
// server side, where I actually fetch the data from db/cms and return it
}