I'm trying to deploy my MEAN stack app to heroku. I successfully committed the app but I can't seem to connect my ng build "dist" file to my server.js file.
here is my server.js code where i'm trying to add the file:
var distDir = __dirname + "/dist/";
app.use(express.static(distDir));
Try this:
const path = require('path');
const express = require('express');
const app = express();
// Serve static files
app.use(express.static(__dirname + '/outputPath'));
// Send all requests to index.html
app.get('/*', function(req, res) {
res.sendFile(path.join(__dirname + '/outputPath/index.html'));
});
// default Heroku port
app.listen(process.env.PORT || 5000)
Where outputPath is the value of your outputPath in your angular.json file (projects -> architect -> build -> options -> outputPath).
Related
Why I get No such a file index.html error
My Folder Structure
here is my Code in server.js.
const PORT = process.env.PORT || 8000
const express = require('express');
const path = require('path')
const http = require('http');
const cors = require('cors');
const app = require('./app.js');
const planetsRouter = require('./routers/planets/planet.router')
const { loadPlanetsData } = require('./models/planets.model')
const server = http.createServer(app)
app.use(cors({ origin: 'http://localhost:3000' }))
app.use(express.json())
app.use(express.static(path.join(__dirname, '..', 'public')))
app.get('/', (req, res) => {
console.log('Res', req)
res.sendFile(path.join(__dirname, '..', 'public', 'index.html'))
})
app.use(planetsRouter)
async function startServer () {
await loadPlanetsData()
server.listen(PORT, () => {
console.log(`Listening on ${PORT}...`)
})
}
startServer()
I got this error
Error: ENOENT: no such file or directory, stat 'C:\Users\kullanıcı\Desktop\Node Js\24-Nasa-Project\server\public\index.html'
This is server.js
If you're getting the error:
Error: ENOENT: no such file or directory, stat 'C:\Users\kullanıcı\Desktop\Node Js\24-Nasa-Project\server\public\index.html'
That means you don't have a file at the path:
C:\Users\kullanıcı\Desktop\Node Js\24-Nasa-Project\server\public\index.html
Just looking at that path, I notice: Users\kullanıcı\Desktop ... that looks like a path from your computer. But you're saying this is on your server ... does your server actually have that folder?
What could be going on is you could have hard-coded that path somewhere in your code during development, and then when you try to use it on your server, it fails because your server doesn't have that path. It doesn't seem possible from the code you provided, but could there be any other code you didn't share?
Alternatively, I noticed you had:
res.sendFile(path.join(__dirname, '..', 'public', 'index.html'))
Why the '..'? It seems your server.js is in your server project root folder, so .. would mean one folder above that .. but the public folder is in the same directory as server.js.
I found the solution I made mistake while writing client package.json it was like this
I have Change it to the this
There is a space after server/public if ı do like first picture I need to write public joint to && symbol
I have never deployed a MERN app to production before. This is going to be my first attempt and I am planning to deploy the app to digital ocean.
So, I have prepared my MERN app for deployment by following the instructions in a Udemy course. My app structure is as follows:
The following are the main changes that I have made to my application:
Because there will be no server created by create-react-app in production, I have written the production routing logic inside server/index.js that essentially says that for any routes not managed by app.use("/api/users", userRoutes) & app.use("/api/download", downloadRoutes), the backend server will server the index.html file inside the client/build folder, which I have created by running the command: npm run build.
server/index.js
const express = require("express");
const path = require("path");
const dotenv = require("dotenv");
const colors = require("colors");
const connectDB = require("./config/db");
const {
notFound,
globalErrorHandler,
} = require("./middleware/errorMiddleware");
const userRoutes = require("./routes/userRoutes");
const downloadRoutes = require("./routes/downloadRoutes");
dotenv.config();
connectDB();
const app = express();
app.use(express.json());
app.use("/api/users", userRoutes);
app.use("/api/download", downloadRoutes);
// Routing logic in production
if (process.env.NODE_ENV === "production") {
app.use(express.static(path.join(__dirname, "/client/build")));
app.get("*", (req, res) => {
res.sendFile(path.resolve(__dirname, "client", "build", "index.html"));
});
}
app.use(notFound);
app.use(globalErrorHandler);
const PORT = process.env.PORT || 5000;
app.listen(PORT, () => {
console.log(`Server listening on port ${PORT}`.yellow.bold);
});
I have changed the process.env.NODE_ENV to production inside the .env file.
After the above-mentioned changes, when I run "npm start" (starts only the backend server) (not "npm run dev" that concurrently starts both the frontend and backend server) and visit http://localhost:5000, I should see my app. Instead, I see the following error.
What am I doing wrong?
As you can see in the error message, Express is looking for an index.html inside server/client/build which does not exist. Fix the path.
app.use(express.static(path.join(__dirname, '../client/build')))
You need to move your entire client folder inside the server and then add the following in the index.js file of the server:
if (process.env.NODE_ENV === "production") {
app.use(express.static("front/build"));
const path = require('path')
app.get("*", (req, res) => {
res.sendFile(path.resolve(__dirname, 'front', 'build',
'index.html'))
})
}
Make sure to run npm run build first.
The Problem
I have a Angular project that i've deployed onto a Linux Server + NodeJS + Express.
When I run the project locally - all of the images load fine.
When I upload the project onto the server and visit the site, it will not load the static images.
My Folder Structure
Project
- dist (Angular DIST Folder)
- assets
- images
- logo.png
- index.html
- styles.css
- etc
- config
- controllers
- node_modules
- routes
- templates
- package.json
- server.js
Server.js
Here is the code for my server.js file:
// imports
const express = require('express');
const bodyParser = require('body-parser');
const path = require('path');
const app = express();
// Parsers
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false}));
// Angular DIST output folder
app.use(express.static(path.join(__dirname, 'dist')));
require("./routes/api.routes")(app);
// Send all other requests to the Angular app
app.get('*', (req, res) => {
res.sendFile(path.join(__dirname, 'dist/index.html'));
});
// set port, listen for requests
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
console.log(`Server is running on port ${PORT}.`);
});
Hoping someone could help me out!
I have actually deployed my React-app in the following way:-
ran the command: npm run build
Already had db.json file with dummy data.
Context, when I run
json-server --watch db.json -p 3001 -d 2000
the entire react-app works on the localhost
installed json-server using npm
created a server.js file
const jsonServer = require('json-server');
const server = jsonServer.create();
const router = jsonServer.router('db.json');
const middlewares = jsonServer.defaults();
const port = process.env.PORT || 3001;
server.use(middlewares);
server.use(router);
server.listen(port);
created the app on heroku and pushed it to heroku master
The website for some reason only works when I run node server.js on my local-machine and it is making requests to my localport.
if that command isn't running the react-app cannot do the axios request to the DB.
I don't know what went wrong.
I used the following tutorial for this: https://github.com/jesperorb/json-server-heroku
My suspicions are that in my code I have created a basUrl.js file in which
export const baseUrl = 'http://localhost:3001/';
How should I change this to fix my problem?
Thanks for your help.
You should link your react folder built with the server (server.js), to do that add:
const express = require('express');
const path = require('path');
app.use(express.static(path.join(__dirname, 'build')));
app.get('/*', function (req, res) {
res.sendFile(path.join(__dirname, 'build', 'index.html'));
});
'build' is your react app's folder created after npm run build into your react app folder.
You have to install path and express modules if not.
And, You should get your json-server database in 'get' function, to use it with a specific url like: /db, just like this:
app.use('/db', middlewares, router);
But you should put /db before /* to not to open database with url /.
So, the result (server.js) will be:
const jsonServer = require('json-server');
const app = jsonServer.create();
const path = require('path');
const express = require('express');
const middlewares = jsonServer.defaults();
const router = jsonServer.router('db.json');
const port = process.env.PORT || 3001;
app.use('/db', middlewares, router);
app.use(express.static(path.join(__dirname, 'build')));
app.get('/*', function (req, res) {
res.sendFile(path.join(__dirname, 'build', 'index.html'));
});
server.listen(port);
I have Heroku running on my JSON server too. You need to correct your API path to be your resource name, for example;
If your resource name in your API is 'blogs';
{
"blogs": [
{
"postTitle": "My First Blog",
then your api path will be;
https://xxxx.herokuapp.com/blogs
OR
export const baseUrl = 'https://xxxx.herokuapp.com/blogs';
You shouldn't need to specify a port, but if you do it will be port 4000, which Heroku uses.
I created an Angular 7 application using the Angular CLI. I added my express server as one knows it. Afterwards I used the command "node server/app.js to start my app, but then in the browser in the "Elements" section there appears <app-root></app-root> without any content. As if the browser knew nothing about the actual Angular application. And when I run the ng serve command it seems to know about the actual Angular application, but there appears a 404 not found error in terms of post and get requests to the data server.
I already had a working Angular4 application with -I guess- the same setup and now same things seem to not work any longer.
I researched all day long to find the solution but for nothing.
I think it is not advantageous to post all my files in here. Comment if I was wrong and I am going to edit them.
Thanks in advance.
My app.js:
"use strict";
var bodyParser = require('body-parser');
const cors = require('cors');
// import { Observable } from 'rxjs';
var express = require("express");
var path = require("path");
var app = express();
app.use(cors());
const router = express.Router();
var nodeModulesPath = path.join(__dirname, "..", "node_modules");
app.use("/node_modules", express.static(nodeModulesPath));
var srcPath = path.join(__dirname, "..", "src");
app.use("/src", express.static(srcPath));
var serverPath = path.join(__dirname);
app.use("/server", express.static(serverPath));
// app.use(bodyParser.json());
var models = require("./models");
models.sequelize.sync({force:true}).then(function() {
console.log("TABELLE ERSTELLT");
// app.use(cors());
app.use("/", router);
app.use(bodyParser
.urlencoded({extended:true})
);
app.use(bodyParser.json());
console.log("after bodyparser");
app.get("/", function(req,res){
res.sendFile(path.join(__dirname, "views", "index.html"));
});
// app.get('/*', function(req, res) {
// res.sendFile(path.join(__dirname, "views", "index.html"));
// });
app.post("/goals/create",function (req, res){
models.Goal.create({
id: req.body.id,
name: req.body.name,
content: req.body.content,
firstGivenValue: req.body.firstGivenValue,
fittingValue: req.body.fittingValue,
someone_would_like_to_implement: req.body.someone_would_like_to_implement,
i_know_how_to_implement_it: req.body.i_know_how_to_implement_it
}).then(function(obj){
console.log(obj.id);
// res.end("erfolgreich");
res.redirect("/");
})
console.log(req.body);
});
app.get("/test",(req, res) => {
res.end("test erfolgreich");
});
app.listen(3000);
});
You mention that you think it used to work for angular 4. Currently you're serving the index.html from the src folder. That's not going to work, your app is a typescript app and will need to be compiled one way or another; not to mention the Angular compiler. In the early days (I think pre 4, but not sure) angular serve also write the served files in a folder in your project, so you could just pick those JIT compiled files up and toss them on a web server, or express server. Those days are gone (with good reason for that matter, mostly performance).
You will now have to create an explicit build (ng build) and tell your express server (app.js) to target your dist folder.
TL;DR:
Run ng build
Replace
var srcPath = path.join(__dirname, "..", "src");
app.use("/src", express.static(srcPath));
With:
var distPath = path.join(__dirname, "..", "dist");
app.use("/dist", express.static(distPath));