Accessing user uploaded images in a deployed MERN app - node.js

I am a relatively new developer and I have made a personal blog app, where a user can create a post and upload an image to use as the thumbnail for that post.
So far the backend and frontend work brilliantly and I am able to get the image, store it locally in a folder on my machine, store the file path in MongoDB and then access it and display it in the UI accordingly.
Now that I'm looking to finally deploy my application I have to figure out a way to upload images to an online cloud storage or something, where I can access them from my frontend as well.
Any suggestions on a good service of this kind and if possible, something free, suitable for my small project? Or any suggestions on an alternative way of dealing with this situation?
Any advice will be greatly appreciated!
Thanks in advance!
NOTE: I plan on deploying my app with Heroku, so if you've ever dealt with this issue directly using Heroku, please share your experience.

Yes, I have several apps that do just this! Sign up for a free MongoDB Atlas account and then you can store the data on their servers and point your Express app to the connection URL. Basically, they will give you a URL like this:
mongodb+srv://your-cluster-name:a232dfjoi39034r#atlas-free-cluster-czaoo.mongodb.net/blog-app?retryWrites=true
Which you can then store in a .env file like this:
MONGODB_URL=mongodb+srv://your-cluster-name:a232dfjoi39034r#atlas-free-cluster-czaoo.mongodb.net/blog-app?retryWrites=true
And access from your app like so:
mongoose.connect(process.env.MONGODB_URL, connectionOptions)
.catch((err) => {
console.log('Error on initial DB connection: ', err);
});
You'll need to load the .env files in your app using an npm packages such as dotenv on the development side. For heroku, you can use the heroku-cli
and set any environment variables for your app like so:
heroku config:set MONGODB_URL=mongodb+srv://your-cluster-name:a232dfjoi39034r#atlas-free-cluster-czaoo.mongodb.net/blog-app?retryWrites=true
Note, the development MongoDB URL could be a connection string to a local instance, such as:
MONGODB_URL=mongodb://localhost:27017/my-blog-app
And the one for heroku can be the MongoDB Atlas cluster.
There are a few other config things to do for Node apps, like having a 'start' script in package.json, which for Express apps created with express-generator looks like:
"scripts": {
"start": "node ./bin/www"
But for your case may be different. It should point to whatever file is the entry point for your server.
You'll also need to set the PORT from process.env.PORT, which heroku will set on their end, and on your end you can just default to 3000:
const PORT = process.env.PORT || 3000;
app.listen(PORT);
If you have any questions, feel free to PM me or just ask here and I can elaborate further. It can be intimidating the first few times, but it's actually really easy to deploy stuff to heroku this way once you get the hang of it! You can also check out the heroku docs for deploying Node apps.

Related

Vercel build never ends

I'm having a problem with Vercel platform, probably because I'm not using it right.
Locally I can deploy the server without problems on port 3000.
But when I want to deploy in Vercel, Build gets stuck at the express function app.listen().
Image Vercel error:
My index.js is like any other and ends with the function:
// listening the server
app.listen(app.get('port'), () => {
console.log('Server on port ', app.get('port'));
});
I've tried everything I don't know what to do anymore, surely I have a conceptual error.
Vercel is for front-end (and serverless)
Sites deployed on Vercel are mainly front-end. (React, Vue, and everything else that becomes HTML/CSS/JS).
By the looks of it you're trying to run a back-end application (Node.js) on Vercel, which it isn't designed for. (Instead, consider using a VPS or a managed environment/app platform)
Vercel also supports serverless functions, which you could use to run your back-end with. These are essentially one-off functions that are run on a new server instance every time a request comes in.
All that considered, if you're indeed trying to build and deploy a front-end app...
A wild guess
Your build script is calling your node application. You might have something like the following in your package.json:
"scripts": {
"build": "tsc && node src"
}
This would run tsc first, then start the application by running the built files.
However, you don't want to start your application as part of the build process -- instead, make the build command only build your app, nothing more.
Then, on Vercel, go to your project's settings page and make sure that command is used to Build your app.
My app doesn't need to be built (I've already got plain HTML/CSS/JS files)
If your app doesn't need to be built at all, go to your project's settings page and remove the "Build Command" entirely.

Incomplete response received from application in Node Js and Mongoose

I installed my api rest in my hosting using cPanel. The routes work perfect and the db is connected. The problem is when I need to use any mongoose method, i.e. model.find({}), the response is
Incomplete response received from application
For other routes, that don't return any data from the DB, works perfect, using json format.
You cannot run MongoDB on shared hosting. Please refer to this thread..
You can use free cloud service like Heroku https://heroku.com or more sophisticated ones like AWS or Azure. If shared hosting deployment is a must, then an option is use external MongoDB instance. Easiest way to get MongoDB instance is using MongoDB Atlas. There is a free sandbox for development purpose.
To create an instance, follow these steps:
Go to https://www.mongodb.com/cloud/atlas, and login/create account
Click 'build a cluster'. Set it as tier-0 for free instance.
Once the cluster is created, click on connect, then choose 'connect your application'
Copy the mongoDB URI and paste it to your code containing something like mongoose.connect(mongoDBAtlasURIhere, { useNewUrlParser: true, useUnifiedTopology: true})
Example of complete tutorial for Node JS: https://medium.com/#sergio13prez/connecting-to-mongodb-atlas-d1381f184369
Hope this helps.

Deploying Node.js, React.js, Express, and Socket.io Application on Heroku

enter image description hereSuccessfully deployed to Heroku and most of our application is working. However, our socket.io pieces (chat, view online users, game updates) are not functioning. We think this may be due to having an instance of socket initialized in the Board.js component and also in the App.js file but not sure if that is the issue or how to resolve.
GitHub: https://github.com/sranney/checkers
Heroku App: https://afternoon-thicket-28146.herokuapp.com/
Any help is greatly appreciated Photo1 1: Server Config for Http Server Photo 2: Shows Proxy Photo 3: Configuring socket in app component Photo 4: Importing socket into app
It looks like you are missing an io.connect statement in your server.js file. Check out this video (https://www.youtube.com/watch?v=y5tRiFJuNOs) along with the source code in the description.

How to use multiple db connection strings depending on the environment in Node.js - Express - Mongo?

During development, using Monk, in my app.js I define the db variable and make it accessible to the router as follows:
var db = monk('localhost:27017/dbname');
[...]
app.use(function(req,res,next){
req.db = db;
next();
});
Now since things seem to be working well, I would like to deploy my app to Heroku. For this purpose, I created an account on mLab to have a db to use in production.
I have set the environment variable MONGODB_URI as
heroku config:set MONGODB_URI=mongodb://user:password#server:port/dbname
and I think now I could use it now in this way:
var db = mongo.db(process.env.MONGOLAB_URI);
Now, I would like to keep my dev environment as it is and when I push to Heroku have instead the production DB. How can I do this?
Maybe it's not complicated but I don't have much experience with databases and production in general so I would appreciate some help.
Ps. Also I see that mLab states that sandbox dbs (the free plan) are not suitable for production. However, given also that my app doesn't make a heavy use of database (mostly just store some data and maybe in the future display something out of it), do you think it is OK if I use a sandbox db anyway? What problems could I encounter doing so?

How to separate express server code from Express business logic code?

All the Node.js tutorials that I have followed have put everything in one file. It includes importing of libraries, routing, database connecting and starting of the server, by say, express.js:
var app = require('express');
app.get('/somePath', blah blah);
app.listen(...);
Now, I have 4 node servers behind an Nginx load balancer. It then becomes very difficult to have the source code updated on all the four servers.
Is there a way to keep the source code out of the server creation code in such a way that I can deploy the source code on the servers as one package? The server creation code should not know anything about routing or database connections. It should only be listening to changes in a folder and the moment a new module meta file appears, it starts hosting that web application.
Much like how we deploy a Java code packaged as war by Maven and deployed to the webapp of Tomcat, because Tomcat instantiation is not part of the source code. In node.js it seems server is also part of the source code.
For now, the packaging is not my concern. My concern is how to separate the logic and how do I point all my servers to one source code base?
Node.js or JavaScript for that matter doesn't have a concept like WAR. But what it does have is something similar. To achieve something WAR like, you would essentially bundle the code into one source file using something like webpack. However, this will probably not work with Node.js modules like http (Express uses `http since it likely calls or relies on native V8/C++ functions/libraries.
You could also use Docker and think of the Docker containers as WARs.
Here is what I figured out as a work around:
Keep the servers under a folder say, "server_clusters" and put different node servers there, namely: node1.js, node2.js, node3.js, node4.js, etc (I know, in the real world, the clusters would be different VMs or CPUs altogether but for now, I simply want to separate server creation logic from source code). These files would have this code snippet:
var constants = require('./prop');
var appBasePath = constants.APP_BASE_DIR;
var appFilePath = appBasePath + "/main";
var app = require(appFilePath);
//each server would have just different port number while everything else would remain constant
app.listen(8080, function (req, res) {
console.log("server started up");
});
Create a properties file that would have the path to the source code and export the object. That simple. This is what is used on line#1 in the above code
Create the source directory project wherever you want on the machine and just update its home directory in the constant file above. The source code directory can export one landing file that will provide the express app to the servers to start:
var express = require('express');
var app = express();
module.exports = app;
With this, there are multiple servers that are pointing to the same source code.
Hope this helps to those who are facing the same problem.
Other approaches are welcome.

Resources