SSR angular 通用和 angular 8 - 在 api 完成之前渲染动态 html 内容

SSR angular universal and angular 8 - rendering dynamic html content before api completes

当我查看页面源代码时,我可以使用 angular 8 和 angular universal 为服务器端渲染动态渲染 html 但我的问题是我正在渲染动态html 在 api 请求完成加载之前,所以我无法从视图页面源中看到动态 html 中的响应 - 如果您需要任何进一步的信息,请告诉我。我 运行 这个命令: 即 npm 运行 build:ssr && npm 运行 serve:ssr 当我查看日志并更改 url 时,我在控制台中收到 [NetworkError] 但应用程序仍按预期 运行s,我需要找出一种方法来加载 api 响应,然后在请求完成后将 html 呈现到页面视图源中,但我 运行 没有想法。

希望你们中的一个能帮上忙, 谢谢

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}`);
});

``

您所描述的是正常行为。只有您在 URL 栏中的原始请求(e.h。当您输入网站地址时)将使用 angular 通用进行预呈现。如果您使用查看源代码(或 Ctrl +U)

,您可以看到这个预渲染的 html

页面显示后,客户端 angular 应用程序接管。当您单击搜索按钮时,它将执行 API 调用并获取结果,这将更新页面。您会看到 html 使用浏览器调试工具中的 Html 检查器,但它不会影响服务器

发送的原始 HTML

对于可能遇到此问题的人 - 我能够通过发出 GET 请求在 SSR 的查看页面源中显示来自 api 请求的数据(在我的例子中是初始搜索结果)在我的应用程序的 app.component 中 - 谢谢