12

I have created angular 4 app and I can run it using ng serve --open and it runs on localhost:4200 , what I want is I have also created api using nodejs in same angular project now I want to run that API at localhost:4200/api so I have tried something like this

my angular 4 and nodejs srtucture look like this

/dist
/server
  /routes
  /server
/src
app.js
package.json

in app.js I used

app.use(express.static(path.join(__dirname, 'dist')));
app.use('/app/api', apiRoutes);
const port = process.env.PORT || '3000';
server.listen(port, () => console.log(`API running on localhost:${port}`));

Once I run using nodemon app.js and go at localhost:3000 it run my angular app and it's fine and than I go at localhost:3000/app/api it's also work fine and good ,

But when I change in angular app it's not auto refresh my app because it's running node app currently for refresh it I need to run ng build and than it will effect my new changes on angular app

So, What I want is to run ng serve --open it will run angular app but not node js api so want to run both and once i change in any from angular app or node js app it must be auto refresh.

kumbhani bhavesh
  • 2,189
  • 1
  • 15
  • 26

3 Answers3

21

You can't have two different applications running on the same port. Angular-cli uses a nodejs server (technically it's webpack-dev-server) behind the scenes when you run ng serve, which means that port is already in use.

There are two possible solutions.

  1. Use your node application to serve the static frontend files. Then you can't really use ng serve (this is probably what you'd do when running live).

  2. Use nodejs with a different port, and use Angular's proxy config, to have Angular think the api port is actually 4200 (this is probably best during development).

This is primarily a concern during development I reckon, since you most likely wont (and shouldn't) be using ng serve live, so option 2 would be my best recommendation.

To configure a proxy, you create a file in your angular application root directory called proxy.config.json with the following content:

{
  "/api/*": {
    "target": "http://localhost:3000",
    "secure": false,
    "changeOrigin": true
  }
}

Then when you run ng serve, you run it with ng serve --proxy-config proxy.config.json instead.

Here's a link to the documentation


Here's an alternative when building for production (solution 1 above):

To build in production you use ng build --prod to create a production ready Angular build and then (assuming you use Express on your node server), use something like app.use(express.static('dist/')) as explained in the Express documentation. I'm not using node myself (I'm using .NET Core) so I'm afraid I can't provide much more in terms of details.

Rob
  • 127
  • 2
  • 10
Nikolaj Dam Larsen
  • 5,455
  • 4
  • 32
  • 45
  • 2
    Also write about the possibility of prerendering javascript on server side: https://github.com/angular/angular-cli/wiki/stories-universal-rendering – Jarek Sep 13 '17 at 06:07
  • That's definitely something to take into account as well, thank you. – Nikolaj Dam Larsen Sep 13 '17 at 06:10
  • 1
    @NikolajDamLarsen i got Error like `[HPM] Error occurred while trying to proxy request /api/users from localhost:4200 to http://localhost:3000 (ECONNREFUSED) (https://nodejs.org/api/errors.html#errors_common_system_errors)` – kumbhani bhavesh Sep 13 '17 at 06:12
  • Are you running your node server as well? – Nikolaj Dam Larsen Sep 13 '17 at 06:13
  • Try adding `"changeOrigin": true,` to the proxy config. – Nikolaj Dam Larsen Sep 13 '17 at 06:18
  • @NikolajDamLarsen it's working on local but how will i run on server, i'm using Heroku server – kumbhani bhavesh Sep 13 '17 at 06:20
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/154289/discussion-between-kumbhanibhavesh-and-nikolaj-dam-larsen). – kumbhani bhavesh Sep 13 '17 at 06:22
  • You shouldn't be using `ng serve` in a production environment. The Angular-cli uses the webpack dev server behind the scenes which, as the name suggest, is meant for use during development only. When running in production, I suggest using option 1 in my answer. – Nikolaj Dam Larsen Sep 13 '17 at 06:22
  • @NikolajDamLarsen how should i do 1 answer? – kumbhani bhavesh Sep 13 '17 at 06:24
  • @NikolajDamLarsen please explain me your first ans i want to do it for both production and development – kumbhani bhavesh Sep 13 '17 at 06:27
  • The first solution can be a bit counter-productive when used in development, since you can't really use `ng serve` then. You're really best off having two different processes for development and production. I've added an explanation of how you might use solution 1 in a production environment, to the answer above. – Nikolaj Dam Larsen Sep 13 '17 at 06:33
  • @kumbhanibhavesh you need to "ng build --prod" then put "dist" folder that generated by build command to your nodejs server app, and add this line to your nodejs app main file (app.js/index.js) : app.use(express.static(__dirname + '/dist')); – T-Bee May 14 '18 at 16:42
  • for me secure was not needed, furthermore if you need to debug add "logLevel": "debug",and you can use [::1] instead of localhost { "/api": { "target": "http://[::1]:3030", "changeOrigin": true, "logLevel": "debug" } } – bormat May 10 '19 at 14:38
2

There is one awesome blog on medium by Daniel Kagan which explain all, here the link. Hot deploy its explain about client hot deployment i added some more code to make client and server hot deployment.

This answer is purely for development hot reload

Step one.

Install concurrently and nodemon

npm i concurrently

npm i nodemon

You can install globally as well with -g flag

Step Two.

Open your servers package.json file, and add following four line to it. Note i have my angular code inside client folder so i did cd client

"buildclient": "cd client && ng build",
"runclient": "cd client && npm start",
"devstart": "nodemon --inspect ./bin/www",
"dev": "npm run buildclient & concurrently --kill-others \"npm run runclient\" \"npm run devstart\""

If you don't want inspect node app then remove --inspect flag.

Step Three.

Go to your angular folder and create file proxy.conf.json add following line to file.

 {
   "/api/*": {
   "target": "http://localhost:3000",
   "secure": false,
   "changeOrigin": true
 }
 }

Step Four.

Add following command inside angular's package.json file

"start": "ng serve --proxy-config proxy.conf.json"

Step Five.

Make angular build output directory inside public folder of server. To do this go to angular.json change build outputPath to ../public following is JSON snippet.

"options": {
        "outputPath": "../public",
        "index": "src/index.html",
        "main": "src/main.ts",
        "polyfills": "src/polyfills.ts",
        "tsConfig": "src/tsconfig.app.json",
        "assets": [
          "src/favicon.ico",
          "src/assets"
        ],
        "styles": [
          "src/styles.css"
        ],
        "scripts": []
      },

Step Six.

Make sure your node express server app.js file read static files from public folder.

app.use(express.static(path.join(__dirname, 'public')));

Step Seven.

npm run dev

Done goto http://localhost:4200 you can see you app there :) all call to /api will get to node express server.

Any changes to server or client will be hot deployed automatically.

NOTE I used Express application generator to create my server and Angular CLI to create angular application. If you did it some other way then some files might not be present

Gaurav Joshi
  • 964
  • 6
  • 12
1

1.first build you angular 6 app run ng build --watch

2.from nodejs app write this middle ware app.use(express.static(path.join(__dirname, './client/dist/client'))); as the folder pointing to client/dist/client is build folder of angular 6 app.

then run nodemon --inspect app.js

make sure to have a hirearchy of folders like this

/myproject /client /dist /client /.... /index.html /app.js /.....

listen to the port you want to run from app.js and run localhost:portno

hope this helps

  • there is nothing to give -1 on this as this is the answer to this question if you want to build your angular app with node on same port and moreover give it a public path also of your build folder and run nodemon --inspect app.js – vishu handa Jan 27 '19 at 15:19
  • I am with u, neutralized. –  Jun 03 '19 at 18:28