I have an angular2 application in heroku, and I'm having trouble with the router. In localhost everything works like a charm, but when I deploy to heroku and try to access by any route that is not index i got 404 error, if I go index, then navigate trough page the routing occurs normally, unless I reload the page, then i get another 404, here's the piece of my package.json used by heroku
"heroku-prebuild": "npm install http-server -g",
"heroku-postbuild": "ng build --target=production --environment=prod && rsync -a dist/* .",
"start": "http-server dist/",
Do I need to setup any express rewriting to be used in my Procfile?
It seems to be a problem from the server , angular knows routing but your server doesnot know all these paths. The simple solution is to redirect all the paths to your main index.html . Like this,
app.get('*', function (req, res) {
res.sendfile('./dist/index.html'); // load our index.html file
});
This will not give any 404 error , all your paths will be redirected to main path i.e index.html and angular routing will run the same as it was in your local host .
Related
How can I start a node js server together with my React App in production environment? I need to call some endpoint provided by the server.
You can use concurrently, which can be installed as devDependency. With this you can execute multiple commands with a scripts entry
{
...
"scripts": {
"start": "concurrently \"yarn start-app\" \"yarn start-server\"",
"start-app": "...",
"start-server": "..."
}
...
"devDependencies": {
"concurrently": "^6.2.0",
...
}
}
In nodeJs main/router file add the following line
1.app.use(express.static((path.join(__dirname, '../../react_client/build'))));
where the second parameter is the path to react index.html file in the build folder. If this line not added will obtain error "unexpected tocken "<" in chunk.js*
app.get('*', (req,res) =>{
res.sendFile(path.resolve(__dirname, '../../react_client/build', 'index.html'));
});
Add this line to handle every get command in the top of every routing function. So that for every get request server will send index.html file
in package.json of node js server add the following
"build": "cd ../../react_client && npm install && npm run build"
where after cd provide the path for react application. So when run "npm run build" from server terminal react application will build and files are available in the build folder
Inside the tag of index.html add "<base href="/" />" else there will be an error "unexpected tocken <" in bundle.js*
In package.json of react application add "proxy": "http://localhost:9000"; this for communicate with Node js where replace 9000 with your node js listening port
Go to node js server directory and run node server_file name
open browser and enter http://localhost:9000/ will provide your index.html file
I'm trying to put an angular application in "production" on a local server that is generated by the http-server tool, but it does not return the of the index.html.
I followed these steps ...
ng build --prod (this throws me the project folder for production like this -> "dist / project-erp")
http-server
web server
Update:
So, I changed the base route to "/" but still happening in same situation :/
After many tests of building the project, the solution to launch it on the Express server (it worked for now) is to just do the command "ng build" instead of "ng build --prod", then the folders "dist / project-erp "put them on the backend server.
I have an Angular 8 application with Universal that I want to deploy to a shared web host production server. I checked with the web host in advance and they told me that hosting an angular universal web app is possible on their shared web hosting. However, whatever I do, I can't get the website to work. When I go to the website I keep seeing the message: "This site can't be reached"
Things I have done so far:
Build project with npm run build:ssr which created a dist folder with a browser and server folder and a server.js file
Move the dist folder to the server inside the public_html folder.
Then accessed the server through SSH and did these:
install Node.js and npm
npm install
npm install pm2 -g
pm2 start dist/server.js
pm2 starts without problems.
These are some of the project files. If any are missing please ask and I'll add them to the question.
Part of the package.json with the scripts:
"scripts": {
"ng": "ng",
"start": "ng serve",
"build": "ng build",
"test": "ng test",
"lint": "ng lint",
"e2e": "ng e2e",
"compile:server": "webpack --config webpack.server.config.js --progress --colors",
"serve:ssr": "node dist/server",
"build:ssr": "npm run build:client-and-server-bundles && npm run compile:server",
"build:client-and-server-bundles": "ng build --prod && ng run ProjectName:server:production --bundleDependencies all"
},
server.js from the build (only the express part, since it's 25000+ lines):
const app = express__WEBPACK_IMPORTED_MODULE_1__();
const PORT = process.env.PORT || 4000;
const DIST_FOLDER = Object(path__WEBPACK_IMPORTED_MODULE_2__["join"])(process.cwd(), 'dist/browser');
// * NOTE :: leave this as require() since this file is built Dynamically from webpack
const { AppServerModuleNgFactory, LAZY_MODULE_MAP, ngExpressEngine, provideModuleMap } = __webpack_require__(144);
// Our Universal express-engine (found # https://github.com/angular/universal/tree/master/modules/express-engine)
app.engine('html', ngExpressEngine({
bootstrap: AppServerModuleNgFactory,
providers: [
provideModuleMap(LAZY_MODULE_MAP)
]
}));
app.set('view engine', 'html');
app.set('views', DIST_FOLDER);
// Example Express Rest API endpoints
// app.get('/api/**', (req, res) => { });
// Serve static files from /browser
app.get('*.*', express__WEBPACK_IMPORTED_MODULE_1__["static"](DIST_FOLDER, {
maxAge: '1y'
}));
// All regular routes use the Universal engine
app.get('*', (req, res) => {
res.render('index', { req });
});
// Start up the Node server
app.listen(PORT, () => {
console.log(`Node Express server listening on http://localhost:${PORT}`);
});
According to several answers on SO or elsewhere you "simply" copy paste the dist folder to the server, run pm2 and your website supposedly works. I feel like there's a lot missing to get it working though.
Does someone know how to properly deploy an Angular Universal website to a production server?
I ended up using a tool in my DirectAdmin console called 'NodeJS Selector', because PM2 kept causing problems for me. It's a tool to install your application, do npm install and start the app. So basically what you'd do using SSH, but in a fancy UI. The setup looks like this:
With my folder structure looking like this:
domains
- appname.com
- public_html
- browser (=> this set as the document root in Apache, because index is located here)
- index.html
- .htaccess
- other files...
- server
- server.js
- package.json
I had my web host do 2 things, because I'm not a root user on the server. They set the documentroot to the browser folder in Apache's httpd.conf file. In the same file they also added proxy settings to port 4000 because that's where my app is running on. So in the httpd.conf file will be something like this:
DocumentRoot "/domains/appname.com/public_html/browser"
<Proxy *>
Order allow,deny
Allow from all
</Proxy>
ProxyPreserveHost On
ProxyRequests Off
ProxyPass / https://localhost:4000/
ProxyPassReverse / https://localhost:4000/
Next in the NodeJS selector you set the root to where the startup file is located (in my case server.js). The package.json needs to be in de public_html folder as well so you can do npm install in the Selector.
To start the app you click 'Run JS script' and choose the serve:ssr option and it runs the node server command.
The Angular docs describe how you have to rewrite some rules on the server. Apache is installed on my web server so I added an .htaccess file with the rewrite rules from the docs. However this app is served by Node and Node can serve the actual paths. So in my case I didn't have to add the .htaccess file with rewrite rules. On the contrary, when I added the .htaccess file it caused the Universal side of my app not to fully render. See this question for more info.
In server.ts file change
const DIST_FOLDER = join(process.cwd(), 'dist/browser');
to
const DIST_FOLDER = join(process.cwd(), 'browser');
Now build the application by npm run build:ssr and copy everything inside of dist folder to your public folder (on host). Remember, instead of pm2 start dist/server.js, you should run pm2 start server.js.
I have a node app which in development is usin 2 servers one for my node side and another for my react side. I am running this using a line in my package.
"scripts": {
"start": "node app.js",
"server": "nodemon --inspect-brk app.js",
"client": "npm start --prefix client",
"dev": "concurrently \"npm run server\" \"npm run client\""
},
when I run npm run devit all works, however when I run node start the server starts running however when you go to the / root url it gives a 404 status error. I assume that's because the app doesn't know where to look for the index.html file or how to kick off the app though I could be completely wrong.
my folder structure is:
As you can see my client folder holds all of the react stuff. the src is the uncompiled react and the build holds my actual index.html fil along with the static folder which holds the compiled react stuff :
so how do I get that to actually work or point me in the direction to look? I guess i've been spoiled with most apps just knowing out of the box how to do this.
UPDATE:
so i have 2 routes currently setup
//initiate route handlers
app.use('/login', require('./routes/authRoutes'));
app.use('/tiles', require('./routes/tileRoutes'));
inside of /login I have for example
router.get('/', (req, res)=>{
some code here...
}
however going to either of those, so if I navigate to localhost:5000/login, I still get a 404 error
If I understand this correctly it works when I run npm run dev because 2 serves spin up. the one server handles all my node code and the second handles all my react code. However I don't want to run 2 servers as my deployment to heroku definitely won't. So how do I merge to 2 so to speak?
Use express.static() function to host static files on your express server. See more here: https://expressjs.com/en/starter/static-files.html
At the root of my project, I have a frontend and backend folder. Both folders contain a package.json that list their dependencies. How do I tell Heroku to run npm install on both folders when deploying the application? It seems like Heroku expects to have a single package.json file by default. Do I have to do something with a Procfile? The Heroku documentation doesn't seem to tell much about my specific question.
Thanks for the help!
I just successfully completed this goal using static files created during a heroku postbuild step, as described in this blogpost. I have a React frontend (could be anything though) and Express API backend. Each process has its own port in dev, but deploying on Heroku uses just one total.
Put the working frontend in a subdirectory of root (such as /frontend).
Put the working backend in a subdirectory of root (such as /api -- the blogpost assumes the backend remains in the root directory -- either way is fine).
Proxy API requests from the frontend to the backend by adding this line to /frontend/package.json (replacing 5000 with your backend port):
"proxy": "http://localhost:5000",
Add the following to api/app.js (or api/index.js) in the backend (be sure the last part is AFTER you define the appropriate backend [or api] paths):
const path = require('path')
// Serve static files from the React frontend app
app.use(express.static(path.join(__dirname, '../frontend/build')))
// AFTER defining routes: Anything that doesn't match what's above, send back index.html; (the beginning slash ('/') in the string is important!)
app.get('*', (req, res) => {
res.sendFile(path.join(__dirname + '/../frontend/build/index.html'))
})
Edit the root directory's /package.json file with something like the following (note that using the concurrently package allows an easy way to run the whole app locally with npm run dev, but only heroku-postbuild is required here):
"scripts": {
"frontend": "cd frontend && npm start",
"api": "cd api && nodemon app.js",
"dev": "concurrently --kill-others-on-fail \"npm run api\" \"npm run frontend\"",
"heroku-postbuild": "cd frontend && npm install && npm run build"
},
Make sure you install all backend package dependencies in the root directory, or you will get errors.
Make sure your /Procfile has something like web: node api/app.js
Seems that you can put a package.json file on the root of the project and use scripts to invoke npm i in both folder.
https://devcenter.heroku.com/articles/nodejs-support#customizing-the-build-process
Something like cd front && npm i && cd ../back && npm i
But i should say that if they are running on different ports, it may not work as it seems that only one web process per procfile is available.
this last point is to confirm.
You can define several entry points for your project in the Procfile :
web: cd front && npm i && npm start
server: cd backend && npm i && npm start
However, you have to upgrade to Hobby at least. It's 7$/dyno/month.