webentwicklung-frage-antwort-db.com.de

(Winkel 6) Angular Universal - Wartet nicht auf den Aufruf der Inhalts-API

SSR kann nicht verwendet werden, wenn Angular Universal mit Seiten verwendet wird, die dynamischen Inhalt verwenden. Alle anderen Seiten funktionieren und die dynamischen Seiten werden mit HTML zurückgegeben, enthalten jedoch keine dynamischen Daten.

Aufgerufene Methode:

ngOnInit() {
  const div = this.renderer.createElement('div');
  const texttest = this.renderer.createText('this works');

  this.renderer.appendChild(div, texttest);
  this.renderer.appendChild(this.content.nativeElement, div);

  this.createLinkForCanonicalURL();

  // The HTML never shows, the method works fine.
  this._contentfulService.getBlogPosts().then(posts => {
    this.blogPosts = _.orderBy(posts, ['sys.createdAt'], ['desc']);
  });
}

Servicemethode

getBlogPosts(query ? : object): Promise<Entry<any>[]> {
  return this.cdaClient.getEntries(Object.assign({
      content_type: CONFIG.contentTypeIds.blogPosts
    }, {
      'fields.private': false
    }))
    .then(res => res.items);
}

Vorlage:

Dies zeigt sich nie in der Quelle.

<li class="blog-post" *ngFor="let post of blogPosts">
  <h1>{{post.fields.title}}</h1>
</li>

Habe die Starter-Kits ausprobiert und funktioniert nicht, wenn sie dieselbe Methode aufrufen. Es wurde auch versucht, render2 zu injizieren und einen Resolver-Dienst zum Abrufen der Daten vor dem Laden. 

Nichts scheint zu funktionieren?

Jede Hilfe wäre dankbar!

EDIT

Dies ist meine server.ts-Datei

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

import { enableProdMode } from '@angular/core';
import * as express from 'express';
import { join } from 'path';

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

// Express server
const app = express();

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

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

// Express Engine
import { ngExpressEngine } from '@nguniversal/express-engine';
// Import module map for lazy loading
import { provideModuleMap } from '@nguniversal/module-map-ngfactory-loader';

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

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

// TODO: implement data requests securely
app.get('/api/*', (req, res) => {
  res.status(404).send('data requests are not supported');
});

// 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('index', { req });
});

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

und mein App-Servermodul

@NgModule({
bootstrap: [AppComponent],

imports: [
    BrowserModule.withServerTransition({ appId: 'app-root' }),

    AppModule,
    ModuleMapLoaderModule,
    ServerModule,
    NoopAnimationsModule,
    ServerTransferStateModule, // comment
]
})
export class AppServerModule { }
9
Smokey Dawson

Verwenden Sie TransferHttpCacheModule , um den HTTP-Aufruf an API zu warten, oder verwenden Sie eine andere Implementierung, die mit TransferState funktioniert, wie ngx-transfer-http .

Mein Beispiel mit Wartezeit von 3 Sekunden: https://github.com/Angular-RU/angular-universal-starter/blob/master/src/app/transfer-back/transfer-back.component.ts

1
gorniv

Versuchen Sie, Ihren Code wie folgt zu bearbeiten:

async ngOnInit() {
  const div = this.renderer.createElement('div');
  const texttest = this.renderer.createText('this works');

  this.renderer.appendChild(div, texttest);
  this.renderer.appendChild(this.content.nativeElement, div);

  this.createLinkForCanonicalURL();

  const posts = await this._contentfulService.getBlogPosts();
  this.blogPosts = _.orderBy(posts, ['sys.createdAt'], ['desc'])

 }
0
Alex Cheremisin

Es scheint so, als würde ein Winkeluniversal nicht auf das Rendern von asynchronen Aufrufen warten.

Ich hatte das gleiche Problem und habe es endlich geschafft, ZoneMacroTaskWrapper zu verwenden, wie in diesem issue erwähnt.

Dies ist der Dienst den ich gemacht habe.

0
Alvaro