0

I'm able to dynamically render html for server side rendering using angular 8 and angular universal when I view page source BUT my issue is that I am rendering the dynamic html before the api request has finished loading so I can't see the response in the dynamic html from the view page source - please let me know if you require any further info. I run this command: i.e. npm run build:ssr && npm run serve:ssr and when I look at the logs and change the url I get a [NetworkError] in the console but the app still runs as expected, I need to figure out a way to load the api response and then render the html into the page view source after the request has finished but I've run out of ideas.

Hopefully one of you guys can help, Thanks

Server.ts

import 'zone.js/dist/zone-node';
import 'localstorage-polyfill';
import { join } from 'path';
import * as express from 'express';

const compression = require('compression');
const sessionStorage = require('sessionstorage');
const DIST_FOLDER = join(process.cwd(), 'dist');
const domino = require('domino');
const fs = require('fs');
const template = fs.readFileSync('./dist/browser/index.html').toString();
const win = domino.createWindow(template);
const proxy = require('http-proxy-middleware');
const cors = require('cors');
const helmet = require('helmet');



Object.assign(global, domino.impl);
(global as any)['KeyboardEvent'] = domino.impl.Event;
global['window'] = win;
global['Node'] = win.Node;
global['navigator'] = win.navigator;
global['Event'] = win.Event;
global['KeyboardEvent'] = win.Event;
global['MouseEvent'] = win.Event;
global['Event']['prototype'] = win.Event.prototype;
global['document'] = win.document;
global['sessionStorage'] = sessionStorage;
global['localStorage'] = localStorage;


// Express server
const app = express();

const PORT = process.env.PORT || 4200;
const {AppServerModuleNgFactory, LAZY_MODULE_MAP, ngExpressEngine, provideModuleMap} = require('./dist/server/main');
app.use(cors());
app.use(compression());


// express-engine
app.engine('html', ngExpressEngine({
    bootstrap: AppServerModuleNgFactory,
    providers: [
        provideModuleMap(LAZY_MODULE_MAP)
    ]
}));

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')));

// Protect website from Clickjacking attack
app.use(helmet.frameguard());
app.use(helmet.xssFilter());

//  Proxy API Endpoints


app.use('/api/profileProxy', proxy(
  {
      target: 'http://xxxxxxx1:9004', // target host
      changeOrigin: true, // needed for virtual hosted sites
      // ws: true, // proxy websockets
      pathRewrite: {
          '^/api/profileProxy': ''
      }
  }
));

app.use('/api/searchProxy', proxy(
  {
      target: 'http://xxxxxx.160:9005', // target host
      changeOrigin: true, // needed for virtual hosted sites
      // ws: true, // proxy websockets
      pathRewrite: {
          '^/api/searchProxy': ''
      }
  }
));



app.get('/sitemap1.xml', function (req, res, next) {
  const file = `${DIST_FOLDER}/sitemap1.xml`;

  fs.exists(file, function (exists) {
    if (exists) {
      res.sendFile(file);
    } else {
      res.status(404).send('404');
    }
  });
});

app.get('/robots.txt', function (req, res, next) {
  const file = `${DIST_FOLDER}/robots.txt`;

  fs.exists(file, function (exists) {
      if (exists) {
          res.sendFile(file);
      } else {
          res.status(404).send('404');
      }
  });
});

// All regular routes use the Universal engine

app.get('*', (req, res) => {
    console.time(`GET: ${req.originalUrl}`);
    console.log(`req-QQQQQQQQQQ: ${req.originalUrl}`);
    res.render(join(DIST_FOLDER, 'browser', 'index.html'), { req });
    console.timeEnd(`GET: ${req.originalUrl}`);
    console.log(`req-timeEnd: ${req.originalUrl}`);
});

// Start up the Node server

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

``

9
  • Are you using absolute urls? Commented May 12, 2020 at 7:38
  • Hi @David in my server.ts file I have the proxy IP addresses and my url looks like this: localhost:4200/api/searchProxy/search/… - where searchProxy is the IP address from the backend _ i'm currently trying to implement a prerender file to see if that will work Commented May 12, 2020 at 8:14
  • If you need any other information, I would be happy to provide it - the prerendering didn't work - it shows the same html and saves it to dist/browser/route/index.html and still gives [networkError] Commented May 12, 2020 at 9:30
  • Can you show your server.ts file? And are you using angular's dev proxy, or a custom one? Commented May 12, 2020 at 9:33
  • I've updated the post with my server.ts file with the proxy I am using Commented May 12, 2020 at 9:52

2 Answers 2

1

What you are describing is normal behaviour. Only your original request (e.h. when you type in the site's adress) in the URL bar will be prerendered using angular universal. This prerendered html is what you can see if you use View Source (or Ctrl +U)

Once the page is displayed, the client side angular app takes over. When you click on the search button, it'll perform an API call and get results, which will update the page. You'll see that html using the Html inspector from your browser's debugging tool, but it will have no impact on the original HTML that has been sent by the server

Sign up to request clarification or add additional context in comments.

2 Comments

hi David - there must be a way to display the search results when I navigate to the new route after I click on search, I'm routing to a new component, while executing an api, I just need to find a way to load the results before the html renders on the server side, i'll continue to research and thanks for your reply
If you want the results loaded before (so prerendered server side), then you need to navigate to the page with the directly from the url bar, not with ajax.
-1

for people that may come across this issue - I was able to display the data from the api request (in my case the initial search results) in the view page source for SSR by making a GET request in the app.component of my app - thanks

enter image description here

2 Comments

Can you please provide the code for fixing this issue, I'm currently having problems with my application exactly. I have a page for individual products, and I want to render all the Html including the head tag after the data is completely resolved.
I'm having the same problem. can you provide the code?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.