2

I am working on an angular app with Contentful CMS which needs to be SSR. I have followed all the steps mentioned here Angular Universal. But its just rendering the static content, not the dynamic content from Contentful. I have also tried TransferState API but its not working with Contentful. My code is

app.server.module.ts

import { NgModule } from '@angular/core';
import { ServerModule, ServerTransferStateModule } from '@angular/platform-server';

import { AppModule } from './app.module';
import { AppComponent } from './app.component';
import { ModuleMapLoaderModule } from '@nguniversal/module-map-ngfactory-loader';

@NgModule({
  imports: [
    AppModule,
    ServerModule,
    ServerTransferStateModule,
    ModuleMapLoaderModule,
   ],
  bootstrap: [AppComponent],
})
export class AppServerModule {}

server.ts

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

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

// Express server
const app = express();

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

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

const domino = require('domino');
const fs = require('fs');
const path = require('path');
const template = fs.readFileSync('./dist/browser/index.html').toString();
const win = domino.createWindow(template);
global['window'] = win;
global['document'] = win.document;

// Our Universal express-engine (found @                 
https://github.com/angular/universal/tree/master/modules/express-engine)
app.engine('html', ngExpressEngine({
  bootstrap: AppServerModuleNgFactory,
  providers: [
    provideModuleMap(LAZY_MODULE_MAP)
  ]
}));

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

// Example Express Rest API endpoints
// app.get('/api/**', (req, res) => { });
// Serve static files from /browser
app.get('*.*', express.static(DIST_FOLDER, {
  maxAge: '1y'
}));

// 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 Express server listening on http://localhost:${PORT}`);
});

contentful.service.ts

private client = createClient({
    space: ENV.contentful.spaceId,
    accessToken: ENV.contentful.token
  });

Am I doing something wrong or need something different for Contentful?

Thanks in advance.

2 Answers2

1

The Contentful SDK does not use Angular's HttpClient module to fetch data so the TransferState API won't work by default.

You first will need to use an adapter for axios as documented here: https://github.com/contentful/contentful.js/blob/master/ADVANCED.md#angular-universal

And then use TransferHttpCacheModule in your app.module.ts: https://github.com/angular/universal/blob/master/docs/transfer-http.md

Kishan
  • 915
  • 6
  • 12
  • I have tried this solution but now getting empty response from Contentful. It is sending all the requests to current domain e.g., http://localhost:4000/entries?sys.id=ID_HERE – Shahbaz Shoukat Apr 07 '20 at 16:19
  • This is a known issue with the `ngx-axios-adapter` library. Here's a workaround: https://github.com/patrickhousley/ngx-axios-adapter/issues/13#issuecomment-627326291 – Kishan May 20 '20 at 12:07
  • I don't know if you are still working on this project, but someone gave me an answer using the axios adapter: https://stackoverflow.com/questions/61910699/contentful-js-using-axios-is-using-localhost – r3plica May 21 '20 at 12:14
  • Just FYI, the `ngx-axios-adapter` is not really maintained. I've tried to used it with ng11 and this is a no go. The logic the adapter does is to intercept the axios call before it sends to the server, get all request details and create a similar request using the ng httpClient. This is what I end up doing. – n4nd0_o Apr 12 '21 at 23:42
0

I have resolved the issue by using Contentful API instead its SDK. Use its API with HttpClient.

API Reference: https://www.contentful.com/developers/docs/references/content-delivery-api/

NOTE: Use full API url in HttpClient without any proxy.

  • What do you do about includes? In the SDK they seem to be merged, when calling the API directly they are a separate object – r3plica May 20 '20 at 09:47
  • I had to write a custom method to resolve the Links by following this documentation: https://www.contentful.com/developers/docs/concepts/links/ – Shahbaz Shoukat May 21 '20 at 10:14