I'm currently trying to build an angular universal app (whith https://github.com/angular/universal-starter), but I'm facing a problem. When I try to reach my API my application doesn't seem to find it.
This is the basic code I started to wrote:
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';
var apiRoute = require("./routes/api");
// 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');
// Our index.html we'll use as our template
const template = readFileSync(join(DIST_FOLDER, 'browser', 'index.html')).toString();
// * NOTE :: leave this as require() since this file is built Dynamically from webpack
const { AppServerModuleNgFactory, LAZY_MODULE_MAP } = require('./dist/server/main.bundle');
// Express Engine
import { ngExpressEngine } from '@nguniversal/express-engine';
// Import module map for lazy loading
import { provideModuleMap } from '@nguniversal/module-map-ngfactory-loader';
// 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', join(DIST_FOLDER, 'browser'));
/* - Example Express Rest API endpoints -
app.get('/api/**', (req, res) => { });
*/
app.use("/api/", apiRoute);
// Server static files from /browser
app.get('*.*', express.static(join(DIST_FOLDER, 'browser'), {
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}`);
});
api.js
var express = require('express');
var router = express.Router();
router.get("/", function (req, res, next) {
console.log("ok test");
res.status(200).json({
title: "Success",
obj: "okSuccess"
});
});
module.exports = router;
app.module.ts
import {BrowserModule} from '@angular/platform-browser';
import {NgModule} from '@angular/core';
import {RouterModule} from '@angular/router';
import { AppComponent } from './app.component';
import { HomeComponent } from './home/home.component';
import {TransferHttpCacheModule} from '@nguniversal/common';
import { HttpClientModule } from '@angular/common/http';
import { HomeService } from './home/home.service';
@NgModule({
declarations: [
AppComponent,
HomeComponent,
],
imports: [
HttpClientModule,
BrowserModule.withServerTransition({appId: 'my-app'}),
RouterModule.forRoot([
{ path: '', component: HomeComponent, pathMatch: 'full'},
{ path: 'lazy', loadChildren: './lazy/lazy.module#LazyModule'},
{ path: 'lazy/nested', loadChildren: './lazy/lazy.module#LazyModule'}
]),
TransferHttpCacheModule,
],
providers: [
HomeService
],
bootstrap: [AppComponent]
})
export class AppModule { }
home.component.ts
import { Component, OnInit } from '@angular/core';
import { HomeService } from './home.service';
@Component({
selector: 'app-home',
template: `<h3>{{ message }}</h3>`
})
export class HomeComponent implements OnInit {
public message: string;
constructor(private homeService: HomeService) { }
ngOnInit() {
this.message = 'Hello';
console.log(this.homeService.apiCall());
}
}
home.service.ts
import { Injectable } from "@angular/core";
import { Headers, Http, Response } from "@angular/http";
import { HttpClient, HttpHeaders, HttpParams, HttpRequest } from '@angular/common/http';
import 'rxjs/Rx';
import { Observable } from "rxjs/Observable";
@Injectable()
export class HomeService {
constructor(private httpClient: HttpClient) { }
apiCall() {
return this.httpClient.get<any>("/api")
.map((response) => {
console.log(response);
return response;
})
.subscribe((response) => {
console.log(response);
return response;
});
}
}
I start to build in development mode by typing npm run start
but I then got the following error
I don't really understand why I got this error, it seems like express does not add my route.
Note: If you look at package.json file, you'll notice that npm run start
only calls ng serve
, so it's not using angular universal. So the following will not work, as there is no '/api' route/handler defined for the front.
this.httpClient.get<any>("/api")
Instructions for starting angular universal rendering mode are here https://github.com/angular/universal-starter#production-also-for-testing-ssrpre-rendering-locally
Besides, when using angular universal, you cannot use relative URLs when performing ajax calls. You must specify the full url (protocol / domain / port if not 80 or 443 for https)
So for now, you should use
this.httpClient.get<any>("http://localhost:4000/api")
if your angular universal is running on port 4000 on localhost
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With