user1203497
user1203497

Reputation: 517

In what way I am supposed to setup my Angular Universal and my backend node.js server

I have working Angular app with nodejs backend, that I deployed and got working. Now I am trying to use Angular Universal and I don't understand how I am supposed to integrate it with my backend server. Do I start my backend server and then I start the frontend server?

This is how my app structure has been set up..

/backend <-- Basically nodejs that deals with api request
   /config
   /node_modules
   [...]
   index.js
/frontend
   [...]
   /dist
       /browser <-- in this I got basically Angular app
       /server
       server.js
   [...]

When I deployed my app without Universal, I just told in my /backend/index.js file- hey if this route matches any of these routers, then it's a API request, but if not then server this static files from /frontend/dist/browser/index.html that was compiled.

Now when I have Angular Universal, tutorial says after I have compiled all the server side rendering stuff I run it with command node dist/server. Now this is where thing get confusing for me, because how is this supposed to work my /backend. My backend is not running.

Do I now start two node servers? In /backend run nodemon index.js and then in /frontend run node dist/server

...or do I have to change my folder structure and somehow integrate them to be part of /frontend/dist/server/

...or I need to write all routes that are in /backend/index.js to /frontend/server.ts

...or I need to add something into /frontend/server.ts file, that gets compiled and when I run node dist/server it also activates my /backend

Currently my /frontend/server.ts looks like this

    // These are important and needed before anything else
import 'zone.js/dist/zone-node';
import 'reflect-metadata';

import { renderModuleFactory } from '@angular/platform-server';
import { enableProdMode } from '@angular/core';

import * as express from 'express';
import { join } from 'path';
import { readFileSync } from 'fs';

// Faster server renders w/ Prod mode (dev mode never needed)
enableProdMode();

// Express server
const app = express();

const PORT = process.env.PORT || 4000;
const DIST_FOLDER = join(process.cwd(), 'dist');

// Our index.html we'll use as our template
const template = readFileSync(join(DIST_FOLDER, 'browser', 'index.html')).toString();

// * NOTE :: leave this as require() since this file is built Dynamically from webpack
const { AppServerModuleNgFactory, LAZY_MODULE_MAP } = require('./dist/server/main');

const { provideModuleMap } = require('@nguniversal/module-map-ngfactory-loader');

app.engine('html', (_, options, callback) => {
  renderModuleFactory(AppServerModuleNgFactory, {
    // Our index.html
    document: template,
    url: options.req.url,
    // DI so that we can get lazy-loading to work differently (since we need it to just instantly render it)
    extraProviders: [
      provideModuleMap(LAZY_MODULE_MAP)
    ]
  }).then(html => {
    callback(null, html);
  });
});

app.set('view engine', 'html');
app.set('views', join(DIST_FOLDER, 'browser'));


// Server static files from /browser
app.get('*.*', express.static(join(DIST_FOLDER, 'browser')));

// All regular routes use the Universal engine
app.get('*', (req, res) => {
  res.render(join(DIST_FOLDER, 'browser', 'index.html'), { req });
});

// Start up the Node server
app.listen(PORT, () => {
  console.log(`Node server listening on http://localhost:${PORT}`);
});

Upvotes: 2

Views: 467

Answers (1)

Michael
Michael

Reputation: 2454

It's completely up to you. I would suggest keeping them separate and running on different ports. If you want to publicly expose them together you can use something like haproxy in front of them to route requests to the right port, or serve the backend from a subdomain eg: api.yourdomain.com

Upvotes: 1

Related Questions