Передача данных со стороны сервера клиенту без http-вызова - PullRequest
0 голосов
/ 06 апреля 2020

Я разрабатываю angular универсальный & node.js как серверное приложение. Я делаю все, как все предлагают, включая официальную документацию.

Обычно, когда клиентское приложение загружается, оно выполняет ajax запрос к API. API размещен на этом моем сервере. и моя цель состоит в том, чтобы избежать этого ajax вызова и рендеринга страницы с сервера уже с этими данными.

Я пытаюсь сделать это как типичный пример:

ngOnInit() {
      let myTransferStateKey = makeStateKey<any>("myDatas");

      if(this.transferState.hasKey(myTransferStateKey)) {
          this.result = this.transferState.get(myTransferStateKey, {});
          this.transferState.remove(myTransferStateKey);
      } else {
          this.http.get("link-to-api").subscribe(response => {
              this.result = response;
              this.transferState.set(myTransferStateKey, this.result);
          });
      }
  }

Так, как я понимаю следующий код будет выполняться на стороне сервера:

      this.http.get("link-to-api").subscribe(response => {
          this.result = response;
          this.transferState.set(myTransferStateKey, this.result);
      });

Таким образом, сторона сервера будет выполнять настоящий http-запрос к самому серверу? Это безобразно! В идеале я должен просто использовать сервис на моем сервере и передать данные для просмотра, а затем сервер отдает html клиенту с этими данными. Надеюсь, вы понимаете, что я имею в виду ..

Кроме того, это мой server.ts, типичный код, который вы, скорее всего, видели в Интернете:

import 'zone.js/dist/zone-node';
import 'reflect-metadata';

import { enableProdMode } from '@angular/core';

import * as express from 'express';
import { join } from 'path';
import { readFileSync } from 'fs';
import { AppServerModule } from './src/main.server';

import {ngExpressEngine} from '@nguniversal/express-engine';

// 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', 'calendar');

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

const domino = require('domino');

const window = domino.createWindow(template);

global['window'] = window;
global['document'] = window.document;

global['requestAnimationFrame'] = cb => cb();

app.engine('html', ngExpressEngine({
    bootstrap: AppServerModule,
}));

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

Так как же решить это изящно? Мне нравится этот универсальный подход и рендеринг на стороне сервера, но пока он выглядит довольно влажным.

Я использую angular 9 версию, node.js 12 версию ...

Позвольте мне уточнить и сформулировать идею и вопрос: как я могу использовать один сервис (один класс / файл и т. д. c) для клиента и сервера? Разница должна быть только в том, что сервер будет использовать службу напрямую, а клиент, когда ему потребуется получить данные - будет использовать ajax запрос к API, а здесь, на стороне сервера - будет использоваться этот класс обслуживания). Я должен сделать так, чтобы он работал вместе с server.ts или что-то вроде этого ...

1 Ответ

1 голос
/ 06 апреля 2020

Так что я думаю, что вы путаетесь с, скажем, Angular Universal против NodeJS Application.

Angular Universal рендерит страницу first , запрошенную на сервере, и с тех пор, как вы щелкаете по сайту, она работает как обычное приложение Angular. Это действительно только для того, чтобы создать иллюзию того, что первая «краска» действительно быстрая, потому что почти вся страница отображается полностью, как только вы заходите на сайт, а не в обычное приложение Angular, где вы получаете пустую страницу, а затем Ваши подписки возвращаются, вы заполняете страницу и т. д. c.

Если вы хотите, чтобы объекты всегда отображались на стороне сервера, то вы, вероятно, хотите создать стандартное приложение Express NodeJS, которое возвращает HTML представлений, а не Angular Universal.

Если вы действительно хотите использовать Universal. Затем вы можете использовать методы angular с именами "isPlatformBrowser" и "isPlatformServer", чтобы проверить, работаете ли вы на сервере или в браузере, а затем вы можете использовать logi c для вызова API или непосредственного получения данных.

Например:

export class PostfeedComponent implements OnInit {

  constructor(@Inject(PLATFORM_ID) private platform: Object) { }

  ngOnInit() {
      if (isPlatformBrowser(this.platform)) {
        // here you can run any browser specific code
      } else {
         // Runs only on server
      }
  }
}

Дополнительная информация:

...